/******************************************************************************\
 *                                                                            *
 *                       Craftmesh Geometric Engine                           *
 *                   Flavio Bertini fl.bertini@gmail.com                      *
 *                                                                            *
 *                                                                            *
\******************************************************************************/


#include "Craftmesh_gengine.h"


using namespace Leap;
using namespace std;


// External resources
extern vector<Mod_SubdivMesh>     _mesh;
extern vector<Con_HandController> _hands;
extern float   _angleXZ;
extern GLfloat _topLeftSelecPlane[3],
_topRightSelecPlane[3],
_bottomRightSelecPlane[3],
_bottomLeftSelecPlane[3];


// invert selected vertecies
void gen_invertSelectPoint(void)
{
	// if there is only one hand and it has selected a mesh
	if (_hands.size() == 1 && _hands[0].meshRef != NULLREF)
	{
		unsigned int meshRef = (unsigned int)_hands[0].meshRef;
		for (int i=1; i<=_mesh[meshRef].nVert; i++)
		{
			_mesh[meshRef].selectedVertices[i-1] = (_mesh[meshRef].selectedVertices[i-1] == DESELECT_POINT) ? SELECT_POINT : DESELECT_POINT;   // selectedVertices [0 ... n-1]
		}
	}
	return;
}

// select point by plane
void gen_selectPointByPlane(int action)
{
	// if there is only one hand that shows five fingers and that hand has selected a mesh
	// select/deselect point
	if (_hands.size() == 1 && _hands[0].fingRef.count() == LEAP_HFOPEN &&
			_hands[0].meshRef != NULLREF)
	{
		// cut-plane vertecies and parameters
		float v1[3] = {-52.73, -46.58, 133.96};
		float v2[3] = {102.69, -49.44, -62.37};
		float v3[3] = {-13.72, 165.97, -148.30};
		// TODO verificare coordinate piano
		// TODO ruotarlo in funzione della mano
		float a = (v2[1] - v1[1])*(v3[2] - v1[2])-(v3[1] - v1[1])*(v2[2] - v1[2]);
		float b = (v3[0] - v1[0])*(v2[2] - v1[2])-(v2[0] - v1[0])*(v3[2] - v1[2]);
		float c = (v2[0] - v1[0])*(v3[1] - v1[1])-(v3[0] - v1[0])*(v2[1] - v1[1]);
		float d = (-a)*v1[0]-b*v1[1]-c*v1[2];

		unsigned int meshRef = (unsigned int)_hands[0].meshRef;
		for (int i=1; i<=_mesh[meshRef].nVert; i++)
		{
			if ((a*_mesh[meshRef].vert[i].x + b*_mesh[meshRef].vert[i].y + c*_mesh[meshRef].vert[i].z + d) < 0)
				_mesh[meshRef].selectedVertices[i-1] = action;  // selectedVertices [0 ... n-1]
		}
	}

	return;
}

// select point by sphere
void gen_selectPointBySphere(int action)
{
	// if there is only one hand that shows one finger and that hand has selected a mesh
	// select/deselect point
	if (_hands.size() == 1 && _hands[0].fingRef.count() == LEAP_OFOPEN &&
			_hands[0].meshRef != NULLREF)
	{
		// sphere position and radius
		Vector spherePos = _hands[0].fingRef[0].tipPosition();
		spherePos.y += LEAP_XZ_PLANE;
		mat_glRotateXZ(_angleXZ, &spherePos);  // rotation imposed by the camera
		float selectDist =_hands[0].selecRadius;
		unsigned int meshRef = (unsigned int)_hands[0].meshRef;
		for (int i=1; i<=_mesh[meshRef].nVert; i++)
		{
			Vector point(_mesh[meshRef].vert[i].x, _mesh[meshRef].vert[i].y, _mesh[meshRef].vert[i].z);
			if (point.distanceTo(spherePos) <= selectDist)
				_mesh[meshRef].selectedVertices[i-1] = action;  // selectedVertices [0 ... n-1]
		}
	}

	return;
}

// deselect all vertices
void gen_deselectAllVertices(void)
{
	// if there is only one hand and it has selected a mesh
	if (_hands.size() == 1 && _hands[0].meshRef != NULLREF)
	{
		unsigned int meshRef = (unsigned int)_hands[0].meshRef;
		for (int i=0; i<_mesh[meshRef].nVert; i++)
		{
			_mesh[meshRef].selectedVertices[i] = DESELECT_POINT;
		}
	}
	return;
}

// Detect edges belonging to more than two faces. True if Two-Manifold
bool gen_TwoManifold(Mod_SubdivMesh *mesh) {

	int i, j;
	int e1, e2;
	bool testTM, localTest;
	Mod_SubdivMesh *workM;
	struct QUEUE {
		int v1;             /* estremi dell'edge */
		int v2;
		int indexVal;       /* indice dell'array val */
		int val[MAXVAL];    /* insieme di face che condividono l'edge */
		struct QUEUE *next;
	} *edge, *tmp, *tmpp;

	testTM = true;
	edge = NULL;

	for (i=1; i <= mesh->nFace; i++) {

		for (j=0; j < mesh->face[i].nVert; j++) { /* non è ancora possibile
                                                utilizzare gli edge della
                                                classe Mod_SubdivMesh */
			e1 = mesh->face[i].vert[j];
			e2 = mesh->face[i].vert[(j+1)%mesh->face[i].nVert];

			if (!edge) { /* non ci sono ancora edge in lista */

				edge = (struct QUEUE*) malloc(sizeof(struct QUEUE));
				if (!edge) ErrorMessage();
				edge->v1 = e1;  edge->v2 = e2;
				edge->indexVal = 1;
				edge->val[0] = i;
				edge->next = NULL;
				tmp = edge;

			} else {

				localTest = false;
				tmpp = edge;
				do {
					if ( ((e1 == tmpp->v1) && (e2 == tmpp->v2)) ||
							((e1 == tmpp->v2) && (e2 == tmpp->v1))) {
						localTest = true;
						break;
					}
					tmpp = tmpp->next;
				} while (tmpp);

				if (localTest) {
					tmpp->val[tmpp->indexVal] = i;
					tmpp->indexVal += 1;
				} else {
					tmp->next = (struct QUEUE*) malloc(sizeof(struct QUEUE));
					if (!tmp->next) ErrorMessage();
					tmp = tmp->next;
					tmp->v1 = e1;  tmp->v2 = e2;
					tmp->indexVal = 1;
					tmp->val[0] = i;
					tmp->next = NULL;

				}
			}
		}
	}

	printf("First Condition\n");
	tmp = edge;
	do {

		if (tmp->indexVal > 2) {
			testTM = false;
			printf("\tFace: ");
			for (i=0; i < tmp->indexVal; i++)
				printf("%d ",tmp->val[i]);
			printf("shared edge (v1--v2): [%d--%d]\n",tmp->v1,tmp->v2);
		}
		tmpp = tmp;
		tmp = tmp->next;
		free(tmpp);
	} while (tmp);

	printf("Second Condition\n");
	if (testTM) {
		workM = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
		if (!workM) ErrorMessage();
		mesh->mod_copyMesh(workM);
		for (i=1; i <= workM->nVert; i++) {
			e1 = 0;
			for (j=0; j < workM->vert[i].val; j++) {
				if (!workM->vert[i].face[j]) e1++;
			}
			if (e1 > 1) {
				printf("\tVertex %d Without Fan Face!!!\n",i);
				testTM = false;
			}
		}
	}

	return testTM;
}

/* Funzione che determina su quale piano coordinato proiettare una face,
   per poterne massimizzare l'area. */
char gen_maximizeProjection(Vertex P1, Vertex P2, Vertex P3) {

	char elimC;
	Vector norm;
	vector<Vector> triangle;

	norm.x = P1.x;
	norm.y = P1.y;
	norm.z = P1.z;
	triangle.push_back(norm);
	norm.x = P2.x;
	norm.y = P2.y;
	norm.z = P2.z;
	triangle.push_back(norm);
	norm.x = P3.x;
	norm.y = P3.y;
	norm.z = P3.z;
	triangle.push_back(norm);

	norm = mat_computeNormal(triangle);

	if (fabs(norm.x) >= fabs (norm.y) &&
			fabs(norm.x) >= fabs (norm.z)) elimC = X;
	else if (fabs(norm.y) >= fabs (norm.x) &&
			fabs(norm.y) >= fabs (norm.z)) elimC = Y;
	else elimC = Z;

	return elimC;
}

/* Funzione che determina se una face è convessa o concava. */
int* gen_shapeFace(Mod_SubdivMesh *mesh, int f, bool *test) {

	int i, j, k, p;
	char prj;
	Vertex P1, P2, P3;
	double d, t;
	double r[2], q[2], v1[2], v2[2], c[2];
	int *Vconc;

	*test = true;

	Vconc = (int*) calloc(mesh->face[f].nVert, sizeof(int));
	if (!Vconc) ErrorMessage();
	p = 0; /* puntatore all'array appena creato */

	/* Si determina su quel piano coordinato è meglio proiettare la face */
	P1.x = mesh->vert[mesh->face[f].vert[0]].x;
	P1.y = mesh->vert[mesh->face[f].vert[0]].y;
	P1.z = mesh->vert[mesh->face[f].vert[0]].z;

	P2.x = mesh->vert[mesh->face[f].vert[1]].x;
	P2.y = mesh->vert[mesh->face[f].vert[1]].y;
	P2.z = mesh->vert[mesh->face[f].vert[1]].z;

	P3.x = mesh->vert[mesh->face[f].vert[2]].x;
	P3.y = mesh->vert[mesh->face[f].vert[2]].y;
	P3.z = mesh->vert[mesh->face[f].vert[2]].z;

	prj = gen_maximizeProjection(P1, P2, P3);

	/* Si controllano le rette per ogni edge con gli altri edge */
	for (i=0; i < mesh->face[f].nVert; i++) {
		switch (prj) {
		case X:
			r[0] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[0]].y;
			r[1] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[0]].z;
			q[0] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[1]].y;
			q[1] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[1]].z;
			break;
		case Y:
			r[0] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[0]].x;
			r[1] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[0]].z;
			q[0] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[1]].x;
			q[1] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[1]].z;
			break;
		default:
			r[0] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[0]].x;
			r[1] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[0]].y;
			q[0] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[1]].x;
			q[1] = mesh->vert[mesh->edge[mesh->face[f].edge[i]].vert[1]].y;
			break;
		}

		for (j=0; j < mesh->face[f].nVert; j++) {
			if (j!=i) { /* si salta lo stesso edge */
				switch (prj) {
				case X:
					v1[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].y;
					v1[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].z;
					v2[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].y;
					v2[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].z;
					break;
				case Y:
					v1[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].x;
					v1[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].z;
					v2[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].x;
					v2[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].z;
					break;
				default:
					v1[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].x;
					v1[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].y;
					v2[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].x;
					v2[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].y;
					break;
				}

				/* Intersezione tra edge_i e edge_j: se il determinante è uguale 0
           le rette sono parallele, altrimenti si verifica l'intersezione */
				d = (r[0] - q[0]) * (-v2[1] + v1[1]) -
						((-v2[0] + v1[0]) * (r[1] - q[1]));

				if (d) {

					/* si determina il parametro t per l'intersezione ... */
					t = 1/d * ( (v1[0] - q[0]) * (-v2[1] + v1[1]) -
							((-v2[0] + v1[0]) * (v1[1] - q[1])) );

					/* ... e il relativo punto di intersezione */
					c[0] = q[0] + (r[0] - q[0]) * t;
					c[1] = q[1] + (r[1] - q[1]) * t;

					/* Se l'intersezione è interna all'edge_j allora siamo in presenza di
             una face concava. */
					if ( t != 0 && t != 1 &&
							(MINOR(v1[0],v2[0]) <= c[0] && c[0] <= MAJOR(v1[0],v2[0])) &&
							(MINOR(v1[1],v2[1]) <= c[1] && c[1] <= MAJOR(v1[1],v2[1]))) {

						*test = false;

						/* il vertice di edge_i più vicino all'intersezione sarà
               quello che causa la concavità */
						d = sqrt(pow((r[0] - c[0]), 2) + pow((r[1] - c[1]), 2));
						t = sqrt(pow((q[0] - c[0]), 2) + pow((q[1] - c[1]), 2));

						if (d < t) { /* r */
							d = 0;
							for (k=0; k < mesh->face[f].nVert; k++) {
								if (Vconc[k] == mesh->edge[mesh->face[f].edge[i]].vert[0])
									d = 1;
							}
							if (!d) {
								Vconc[p] = mesh->edge[mesh->face[f].edge[i]].vert[0];
								p++;
							}
						} else { /* q */
							d = 0;
							for (k=0; k < mesh->face[f].nVert; k++) {
								if (Vconc[k] == mesh->edge[mesh->face[f].edge[i]].vert[1])
									d = 1;
							}
							if (!d) {
								Vconc[p] = mesh->edge[mesh->face[f].edge[i]].vert[1];
								p++;
							}
						}
					}
				}
			}
		}
	}

	return Vconc;
}

/* Funzione che determina se i vertici di una faccetta sono complanari. */
bool gen_complaneTest(Mod_SubdivMesh *mesh, int f, double *param) {

	int j;
	Vertex v1, v2, v3;   /* punti con cui determinare il piano */
	double a, b, c, d;  /* coefficienti del piano */
	bool test;

	test = true;
	j = 0;

	v1.x = mesh->vert[mesh->face[f].vert[0]].x;
	v1.y = mesh->vert[mesh->face[f].vert[0]].y;
	v1.z = mesh->vert[mesh->face[f].vert[0]].z;

	v2.x = mesh->vert[mesh->face[f].vert[1]].x;
	v2.y = mesh->vert[mesh->face[f].vert[1]].y;
	v2.z = mesh->vert[mesh->face[f].vert[1]].z;

	// i 3 vertici non devono essere collineari
	for(int v=0;v<mesh->face[f].nVert;v++){
		if(!gen_pointDline(mesh->vert[mesh->face[f].vert[v]],v1,v2,0.000002)){
			v3.x = mesh->vert[mesh->face[f].vert[v]].x;
			v3.y = mesh->vert[mesh->face[f].vert[v]].y;
			v3.z = mesh->vert[mesh->face[f].vert[v]].z;
			j = 1;
			break;
		}
	}

	j = 0;
	/* Per determinare i coefficienti del piano passante per tre vertici,
     si calcola il determinante di questo sistema:

        | (X  - x1) (Y  - y1) (Z  - z1) |
        | (x2 - z1) (y2 - z1) (z2 - z1) |
        | (x3 - z1) (y3 - z1) (z3 - z1) |

    in particolare:

        | (X  - x1) (Y  - y1) (Z  - z1) | (X  - x1) (Y  - y1)
        | (x2 - x1) (y2 - y1) (z2 - z1) | (x2 - x1) (y2 - y1)
        | (x3 - x1) (y3 - y1) (z3 - z1) | (x3 - x1) (y3 - y1)

   1' -> [(X - x1) * (y2 - y1) * (z3 - z1)] - [(X - x1) * (z2 - z1) * (y3 - y1)]
   2' -> [(Y - y1) * (z2 - z1) * (x3 - x1)] - [(Y - y1) * (x2 - x1) * (z3 - z1)]
   3' -> [(Z - z1) * (x2 - x1) * (y3 - y1)] - [(Z - z1) * (y2 - y1) * (x3 - x1)]

    dalla 1' ottengo (a) e (d) parziale
    dalla 2' ottengo (b) e (d) parziale
    dalla 3' ottengo (c) e (d) parziale

    sommando le (d) parziali ottenute si ottiene:

    aX + bY + cZ + d = 0
	 */

	a = ((v2.y - v1.y) * (v3.z - v1.z)) - ((v2.z - v1.z) * (v3.y - v1.y));
	b = ((v2.z - v1.z) * (v3.x - v1.x)) - ((v2.x - v1.x) * (v3.z - v1.z));
	c = ((v2.x - v1.x) * (v3.y - v1.y)) - ((v2.y - v1.y) * (v3.x - v1.x));
	d = ( (-v1.x * (v2.y - v1.y) * (v3.z - v1.z)) -
			(-v1.x * (v2.z - v1.z) * (v3.y - v1.y)) ) +
					( (-v1.y * (v2.z - v1.z) * (v3.x - v1.x)) -
							(-v1.y * (v2.x - v1.x) * (v3.z - v1.z)) ) +
							( (-v1.z * (v2.x - v1.x) * (v3.y - v1.y)) -
									(-v1.z * (v2.y - v1.y) * (v3.x - v1.x)) );

	param[0] = a;  param[1] = b;  param[2] = c;  param[3] = d;

	/* Se la faccetta è triangolare i vertici saranno sicuramente complanari */
	if ( mesh->face[f].nVert == 3 ) return test;

	/* Ottenuto il piano si testano tutti gli altri vertici della faccetta */
	for (j=3; j < mesh->face[f].nVert; j++)
		if ( (mesh->vert[mesh->face[f].vert[j]].x * a +
				mesh->vert[mesh->face[f].vert[j]].y * b +
				mesh->vert[mesh->face[f].vert[j]].z * c + d) != 0)
			test = false;

	return test;
}

/* Funzione che determina se un insieme di vertici è complanare */
bool gen_complaneVectorTest(vector<Vertex> v){
	std::vector<double>::size_type j;
	Vertex v1, v2, v3;   /* punti con cui determinare il piano */
	double a, b, c, d;  /* coefficienti del piano */
	double param[4];
	bool test;

	test = true;
	j = 0;

	v1.x = v[0].x;
	v1.y = v[0].y;
	v1.z = v[0].z;

	v2.x = v[1].x;
	v2.y = v[1].y;
	v2.z = v[1].z;

	// i 3 vertici non devono essere collineari
	for(j=0;j<v.size();j++){
		if(!gen_pointDline(v[j],v1,v2,0.000002)){
			v3.x = v[j].x;
			v3.y = v[j].y;
			v3.z = v[j].z;
			j = 1;
			break;
		}
	}

	j = 0;
	/* Per determinare i coefficienti del piano passante per tre vertici,
	     si calcola il determinante di questo sistema:

	        | (X  - x1) (Y  - y1) (Z  - z1) |
	        | (x2 - z1) (y2 - z1) (z2 - z1) |
	        | (x3 - z1) (y3 - z1) (z3 - z1) |

	    in particolare:

	        | (X  - x1) (Y  - y1) (Z  - z1) | (X  - x1) (Y  - y1)
	        | (x2 - x1) (y2 - y1) (z2 - z1) | (x2 - x1) (y2 - y1)
	        | (x3 - x1) (y3 - y1) (z3 - z1) | (x3 - x1) (y3 - y1)

	   1' -> [(X - x1) * (y2 - y1) * (z3 - z1)] - [(X - x1) * (z2 - z1) * (y3 - y1)]
	   2' -> [(Y - y1) * (z2 - z1) * (x3 - x1)] - [(Y - y1) * (x2 - x1) * (z3 - z1)]
	   3' -> [(Z - z1) * (x2 - x1) * (y3 - y1)] - [(Z - z1) * (y2 - y1) * (x3 - x1)]

	    dalla 1' ottengo (a) e (d) parziale
	    dalla 2' ottengo (b) e (d) parziale
	    dalla 3' ottengo (c) e (d) parziale

	    sommando le (d) parziali ottenute si ottiene:

	    aX + bY + cZ + d = 0
	 */

	a = ((v2.y - v1.y) * (v3.z - v1.z)) - ((v2.z - v1.z) * (v3.y - v1.y));
	b = ((v2.z - v1.z) * (v3.x - v1.x)) - ((v2.x - v1.x) * (v3.z - v1.z));
	c = ((v2.x - v1.x) * (v3.y - v1.y)) - ((v2.y - v1.y) * (v3.x - v1.x));
	d = ( (-v1.x * (v2.y - v1.y) * (v3.z - v1.z)) -
			(-v1.x * (v2.z - v1.z) * (v3.y - v1.y)) ) +
					( (-v1.y * (v2.z - v1.z) * (v3.x - v1.x)) -
							(-v1.y * (v2.x - v1.x) * (v3.z - v1.z)) ) +
							( (-v1.z * (v2.x - v1.x) * (v3.y - v1.y)) -
									(-v1.z * (v2.y - v1.y) * (v3.x - v1.x)) );

	param[0] = a;  param[1] = b;  param[2] = c;  param[3] = d;

	/* Se l'insieme è dato da soli 3 vertici, questi saranno sicuramente complanari */
	if ( v.size() == 3 ) return test;

	/* Ottenuto il piano si testano tutti gli altri vertici */
	for (j=3; j < v.size(); j++)
		if ((v[j].x * param[0] + v[j].y * param[1] + v[j].z * param[2] + param[3]) != 0)
			test = false;

	return test;
}

/* Funzione che determina se una faccia giace su un piano */
bool gen_complaneFace(Mod_SubdivMesh *mesh, int f, double *param){

	int count = 0;
	// verifico che tutti i punti della faccia f appartengano al piano individuato da param
	for(int v=0;v<mesh->face[f].nVert;v++){
		if( abs(mesh->vert[mesh->face[f].vert[v]].x * param[0] +
				mesh->vert[mesh->face[f].vert[v]].y * param[1] +
				mesh->vert[mesh->face[f].vert[v]].z * param[2] + param[3]) <= 0.000002 ){

			count++;
		}
	}

	if(count == mesh->face[f].nVert)
		return true;
	else
		return false;
}

/* Funzione che determina se la face presenta un'intersezione tra i suoi edge;
   per rilevarlo determina se gli angoli creati di volta in volta in ogni
   vertice dai successivi, risultano crescenti. */
bool gen_crossEdge(Mod_SubdivMesh *mesh, int f) {

	int i, j, sj;
	double a, b, c, degree, tmp;
	Vertex P0, P1, P2;
	bool test;

	test = true;

	for (j=0; j < mesh->face[f].nVert; j++) {

		sj = (j + 1) % mesh->face[f].nVert;

		P0.x = mesh->vert[mesh->face[f].vert[j]].x;
		P0.y = mesh->vert[mesh->face[f].vert[j]].y;
		P0.z = mesh->vert[mesh->face[f].vert[j]].z;
		P1.x = mesh->vert[mesh->face[f].vert[sj]].x;
		P1.y = mesh->vert[mesh->face[f].vert[sj]].y;
		P1.z = mesh->vert[mesh->face[f].vert[sj]].z;

		degree = 0;
		c = sqrt(pow((P1.x - P0.x), 2) + pow((P1.y - P0.y), 2) +
				pow((P1.z - P0.z), 2));

		/* Torema di Carnot: si controllano tutti gli angoli a giro. */
		i = j + 2;
		do {

			P2.x = mesh->vert[mesh->face[f].vert[i]].x;
			P2.y = mesh->vert[mesh->face[f].vert[i]].y;
			P2.z = mesh->vert[mesh->face[f].vert[i]].z;

			a = sqrt(pow((P2.x - P1.x), 2) + pow((P2.y - P1.y), 2) +
					pow((P2.z - P1.z), 2));
			b = sqrt(pow((P2.x - P0.x), 2) + pow((P2.y - P0.y), 2) +
					pow((P2.z - P0.z), 2));

			/* a^2 = b^2 + c^2 -2*b*c*cos(alpha) */
			tmp = acos( -(((a * a) - (b * b) - (c * c)) / (2 * b *c)) );

#if DEBUG_GLUE
			printf("DEGREE: %g\n",tmp);
#endif

			if ( tmp > degree ) degree = tmp;
			else { test = false; break; }

			i = (i + 1) % mesh->face[f].nVert;

		} while (i != j);

	}

	return test;
}

// Funzione che rileva tutti gli elementi della mesh che, data la tolleranza,rientrano in un intorno di P
void gen_inquiryElementsMesh(Mod_SubdivMesh *mesh, Vertex P, float toll) {

	int j;
	Vertex p0, p1;
	double param[4];  /* coefficienti del piano per il test di complanarità */

	printf("========================================\n");
	printf("Nell'intorno (± %g) del punto indicato (%g,%g,%g) risiedono\n",
			toll,P.x,P.y,P.z);
	printf("i seguenti vertex: ");
	for (j=1; j <= mesh->nVert; j++) {

		if (fabs(P.x - mesh->vert[j].x) <= toll &&
				fabs(P.y - mesh->vert[j].y) <= toll &&
				fabs(P.z - mesh->vert[j].z) <= toll) printf("%d ",j);
	}

	printf("\ni seguenti edge: ");
	for (j=1; j <= mesh->nEdge; j++) {

		p0.x = mesh->vert[(mesh->edge[j].vert[0])].x;
		p0.y = mesh->vert[(mesh->edge[j].vert[0])].y;
		p0.z = mesh->vert[(mesh->edge[j].vert[0])].z;

		p1.x = mesh->vert[(mesh->edge[j].vert[1])].x;
		p1.y = mesh->vert[(mesh->edge[j].vert[1])].y;
		p1.z = mesh->vert[(mesh->edge[j].vert[1])].z;

		if (gen_pointDsegment(P, p1, p0, toll)) printf("%d ",j);
	}

	printf("\nle seguenti face: ");
	for (j=1; j <= mesh->nFace; j++) {

		param[0] = 0;  param[1] = 0;  param[2] = 0;  param[3] = 0;

		if (gen_complaneTest(mesh, j, param)) {  /* Vertici complanari */

			if (gen_pointDplane(P, param, mesh, j, toll)) printf("%d ",j);

		} else {  /* Vertici NON complanari */

			if (gen_pointDiperPlane(P, mesh, j, toll)) printf("%d ",j);
		}
	}

	printf("\n========================================\n");
	return;
}

/* Funzione che determina se la distanza di un vertex da
   un edge, definito dai suoi vertici, rientra in un valore
   di tolleranza. */
bool gen_pointDsegment(Vertex v, Vertex p0, Vertex p1, float e) {

	/* r: retta passante per p0(x0,y0,z0) e p1(x1,y1,z1) */
	/* p: piano passante per v(xV,yV,zV) e ortogonale a r */
	/* h: proiezione di v su r ovvero intersezione di r e p */

	double a, b, c, d;  /* coefficienti di p */
	double t;           /* parametro di h */
	double xh, yh, zh;  /* coordinate di h */
	double D;           /* distanza da v a h */

	/* si determinano i coefficienti di p considerando r passante per p0 e p1:
        l = (x1 - x0) = a;
        m = (y1 - y0) = b;
        n = (z1 - z0) = c. */
	a = (p1.x - p0.x);
	b = (p1.y - p0.y);
	c = (p1.z - p0.z);

	/* si determina il termine noto d di p, imponendo che il piano passi per v:
        ax + by + cz + d = 0 */
	d = -(a * v.x) - (b * v.y) - (c * v.z);

	/* si determina il parametro t di r dato dall'intersezione (r p):
        (ax0 + by0 + cz0 + d) + (al + bm + cn)t = 0 */
	t = -(a*p0.x + b*p0.y + c*p0.z + d)/(a*a + b*b + c*c);

	/* si determinano le coordinate di h:
        x = x0 + lt;
        y = y0 + mt;
        z = z0 + nt. */
	xh = p0.x + a*t;
	yh = p0.y + b*t;
	zh = p0.z + c*t;

	/* si determina la distanza tra v e h:
        dist = ((x1 - x0)^2 + (y1 - y0)^2 + (z1 - z0)^2) ^ 1/2 */
	D = sqrt(pow((xh - v.x), 2) + pow((yh - v.y), 2) + pow((zh - v.z), 2));

	/* test:
        la proiezione di p su r deve appartenere al segmento p0-p1 e
        la distanza di p da r deve essere minore della tolleranza epsilon
        MIN(x1,x0) - tolleranza <= hx <= MAX(x1,x0) + tolleranza AND
        MIN(y1,y0) - tolleranza <= hy <= MAX(y1,y0) + tolleranza AND
        MIN(z1,z0) - tolleranza <= hz <= MAX(z1,z0) + tolleranza AND
        distanza(vertex,edge) <= tolleranza */
	if ( (MINOR(p1.x, p0.x) <= xh && xh <= MAJOR(p1.x, p0.x)) &&
			(MINOR(p1.y, p0.y) <= yh && yh <= MAJOR(p1.y, p0.y)) &&
			(MINOR(p1.z, p0.z) <= zh && zh <= MAJOR(p1.z, p0.z)) &&
			(D <= e) ) return true;
	else return false;

}

/* Funzione che determina se la distanza di un vertex da una retta,
 * individuata da due suoi punti, rientra in un valore di tolleranza. */
bool gen_pointDline(Vertex v, Vertex p0, Vertex p1, float e) {

	/* r: retta passante per p0(x0,y0,z0) e p1(x1,y1,z1) */
	/* p: piano passante per v(xV,yV,zV) e ortogonale a r */
	/* h: proiezione di v su r ovvero intersezione di r e p */

	double a, b, c, d;  /* coefficienti di p */
	double t;           /* parametro di h */
	double xh, yh, zh;  /* coordinate di h */
	double D;           /* distanza da v a h */

	/* si determinano i coefficienti di p considerando r passante per p0 e p1:
        l = (x1 - x0) = a;
        m = (y1 - y0) = b;
        n = (z1 - z0) = c. */
	a = (p1.x - p0.x);
	b = (p1.y - p0.y);
	c = (p1.z - p0.z);

	/* si determina il termine noto d di p, imponendo che il piano passi per v:
        ax + by + cz + d = 0 */
	d = -(a * v.x) - (b * v.y) - (c * v.z);

	/* si determina il parametro t di r dato dall'intersezione (r p):
        (ax0 + by0 + cz0 + d) + (al + bm + cn)t = 0 */
	t = -(a*p0.x + b*p0.y + c*p0.z + d)/(a*a + b*b + c*c);

	/* si determinano le coordinate di h:
        x = x0 + lt;
        y = y0 + mt;
        z = z0 + nt. */
	xh = p0.x + a*t;
	yh = p0.y + b*t;
	zh = p0.z + c*t;

	/* si determina la distanza tra v e h:
        dist = ((x1 - x0)^2 + (y1 - y0)^2 + (z1 - z0)^2) ^ 1/2 */
	D = sqrt(pow((xh - v.x), 2) + pow((yh - v.y), 2) + pow((zh - v.z), 2));

	/* test: la distanza di p da r deve essere minore della tolleranza epsilon */
	if (D <= e) return true;
	else return false;
}

/* Funzione che determina se la distanza di un punto da una face,
   definita dai suoi vertici, rientra in un valore di tolleranza. */
bool gen_pointDplane(Vertex P, double *param, Mod_SubdivMesh *mesh, int f, float e) {

	int j;
	double d, t, bh;
	double b[2], h[2], p1[2], p2[2], i[2];  /* proiezione 2D dei punti */
	Vertex B, H, P1, P2, P3;                 /* baricentro della face, proiezione
                                             di P sul piano-face e punti del
                                             piano face */
	char elim;
	bool test;

	test = true;

	/* Distanza di un punto da un piano:

                |a*x0 + b*y0 + c*z0 + d|
        dist = --------------------------
                 sqrt(a^2 + b^2 + c^2 )
	 */
	d = fabs( P.x * param[0] + P.y * param[1] + P.z * param[2] + param[3]) /
			sqrt(pow(param[0], 2) + pow(param[1], 2) + pow(param[2], 2));

	if ( !(d <= e) ) { test = false; return test; }

	/* Se la distanza rientra nella tolleranza, si prosegue il test verificando
     che la proiezione del punto sul piano sia interna alla face. */

	/* Si determina il baricentro della face. */
	B.x = 0;  B.y = 0;  B.z = 0;
	for (j=0; j < mesh->face[f].nVert; j++) {
		B.x += mesh->vert[mesh->face[f].vert[j]].x;
		B.y += mesh->vert[mesh->face[f].vert[j]].y;
		B.z += mesh->vert[mesh->face[f].vert[j]].z;
	}
	B.x = B.x / mesh->face[f].nVert;
	B.y = B.y / mesh->face[f].nVert;
	B.z = B.z / mesh->face[f].nVert;

	/* Si determina la proiezione del punto P sul piano della face:
     una retta perpendicolare al piano è data dal vettore (a,b,c), è sufficiente
     imporre che passi per il punto P, e determinare l'intersezione di tale
     retta con il piano.

      p =>   ax + by + cz + d = 0

           {  x = x0 + at
      r => {  y = y0 + bt
           {  z = z0 + ct

      Determinando t come:

        a(x0 + at) + b(y0 + bt) + c(z0 + ct) + d = 0

      è possibile trovare la proiezione H di P sul piano p.
	 */

	t =  -(param[0] * P.x + param[1] * P.y + param[2] * P.z + param[3]) /
			(pow(param[0], 2) + pow(param[1], 2) + pow(param[2], 2));

	H.x = P.x + param[0]*t;
	H.y = P.y + param[1]*t;
	H.z = P.z + param[2]*t;

	/* A questo punto si hanno una serie di punti complanari: i vertici della face,
   il suo baricentro e la proiezione del punto sul piano-face.
   Prima Fase: per determinare le intersezioni tra gli edge e la retta BH è più
               semplice riportarsi ad una situazione 2D. Quindi, per scegliere
               quale coordinata eliminare, si determina la normale del piano e
               si elimina la coordinata con valore assoluto maggiore, in questo
               modo si massimizza l'area del poligono 2D.
   Seconda Fase: tutti i punti di intersezione con gli edge, devono avere
                 distanza maggiore rispetto alla lunghezza BH, oppure, il
                 punto di intersezione deve essere esterno all'edge e al
                 segmento BH, se tutto ciò si verifica il punto P è interno
                 alla face. */
	/* eliminazione coordinata del baricentro e della proiezione */
	P1.x = mesh->vert[mesh->face[f].vert[0]].x;
	P1.y = mesh->vert[mesh->face[f].vert[0]].y;
	P1.z = mesh->vert[mesh->face[f].vert[0]].z;
	P2.x = mesh->vert[mesh->face[f].vert[1]].x;
	P2.y = mesh->vert[mesh->face[f].vert[1]].y;
	P2.z = mesh->vert[mesh->face[f].vert[1]].z;
	P3.x = mesh->vert[mesh->face[f].vert[2]].x;
	P3.y = mesh->vert[mesh->face[f].vert[2]].y;
	P3.z = mesh->vert[mesh->face[f].vert[2]].z;

	elim = gen_maximizeProjection(P1, P2, P3);

	switch (elim) {
	case X:
		b[0] = B.y;  b[1] = B.z;
		h[0] = H.y;  h[1] = H.z;
		break;
	case Y:
		b[0] = B.x;  b[1] = B.z;
		h[0] = H.x;  h[1] = H.z;
		break;
	default:
		b[0] = B.x;  b[1] = B.y;
		h[0] = H.x;  h[1] = H.y;
		break;
	}
	/* distanza bh */
	bh = sqrt(pow((h[0] - b[0]), 2) + pow((h[1] - b[1]), 2));

	/* controllo delle intersezioni con gli edge */
	for (j=0; j < mesh->face[f].nVert; j++) {

		switch (elim) { /* eliminazione coordinata dell'edge */
		case X:
			p1[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].y;
			p1[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].z;
			p2[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].y;
			p2[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].z;
			break;
		case Y:
			p1[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].x;
			p1[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].z;
			p2[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].x;
			p2[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].z;
			break;
		default:
			p1[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].x;
			p1[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[0]].y;
			p2[0] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].x;
			p2[1] = mesh->vert[mesh->edge[mesh->face[f].edge[j]].vert[1]].y;
			break;
		}

		/* intersezione p1p2_bh: se il determinante è uguale 0 le rette sono
       parallele, altrimenti si verifica l'intersezione */
		d = (h[0] - b[0]) * (-p2[1] + p1[1]) - ((-p2[0] + p1[0]) * (h[1] - b[1]));

		if (d) {

			/* si determina il parametro t per l'intersezione su bh ... */
			t = 1/d * ( (p1[0] - b[0]) * (-p2[1] + p1[1]) -
					((-p2[0] + p1[0]) * (p1[1] - b[1])) );

			/* ... e il relativo punto di intersezione */
			i[0] = b[0] + (h[0] - b[0]) * t;
			i[1] = b[1] + (h[1] - b[1]) * t;

			/* è possibile determinare la distanza bi */
			d = sqrt(pow((i[0] - b[0]), 2) + pow((i[1] - b[1]), 2));

			if ( (d + e) < bh) { /* se l'intersezione è "più vicina" si verifica
                              che sia esterna all'edge e al segmento bh */

				if ( ((MINOR(b[0],h[0]) <= i[0] && i[0] <= MAJOR(b[0],h[0])) &&
						(MINOR(b[1],h[1]) <= i[1] && i[1] <= MAJOR(b[1],h[1]))) &&
						((MINOR(p1[0],p2[0]) <= i[0] && i[0] <= MAJOR(p1[0],p2[0])) &&
								(MINOR(p1[1],p2[1]) <= i[1] && i[1] <= MAJOR(p1[1],p2[1]))) ) {
					test = false;
					break;
				}
			}
		}
	}

	return test;
}

/* Funzione che determina se un punto è interno ad una face convessa */
bool gen_pointDplane2D(Vertex q, Mod_SubdivMesh *mesh, int f, float e) {

	/*  Si calcola la somma degli angoli tra il punto q e ogni coppia di vertici degli edge della faccia.
	 * Questa somma sarà pari a 2pi se il punto si trova sul piano del poligono e al suo interno. */

	double m1,m2;
	double anglesum=0,costheta;
	Vertex p1,p2;

	for (int i=0;i<mesh->face[f].nVert;i++) {
		p1.x = mesh->vert[mesh->face[f].vert[i]].x - q.x;
		p1.y = mesh->vert[mesh->face[f].vert[i]].y - q.y;
		p1.z = mesh->vert[mesh->face[f].vert[i]].z - q.z;
		p2.x = mesh->vert[mesh->face[f].vert[(i+1)%mesh->face[f].nVert]].x - q.x;
		p2.y = mesh->vert[mesh->face[f].vert[(i+1)%mesh->face[f].nVert]].y - q.y;
		p2.z = mesh->vert[mesh->face[f].vert[(i+1)%mesh->face[f].nVert]].z - q.z;

		m1 = sqrt(p1.x*p1.x + p1.y*p1.y + p1.z*p1.z);
		m2 = sqrt(p2.x*p2.x + p2.y*p2.y + p2.z*p2.z);
		if (m1*m2 <= e)
			return(true); /* siamo su un vertice */
		else
			costheta = (p1.x*p2.x + p1.y*p2.y + p1.z*p2.z) / (m1*m2);

		anglesum += acos(costheta);
	}
	if(abs(6.283185307179586476925287 - anglesum) <= e)
		return true;
	else
		return false;
}

/* Funzione che determina se un punto è interno ad una face convessa individuata dai suoi vertici */
bool gen_pointDplane2DV(Vertex q, vector<Vertex> vert, float e) {

	/*  Si calcola la somma degli angoli tra il punto q e ogni coppia di vertici degli edge della faccia.
	 * Questa somma sarà pari a 2pi se il punto si trova sul piano del poligono e al suo interno. */

	double m1,m2;
	double anglesum=0,costheta;
	Vertex p1,p2;

	for (std::vector<double>::size_type i=0;i!=vert.size();i++) {
		// printf("poligono %g %g %g\n",vert[i].x,vert[i].y,vert[i].z);
		p1.x = vert[i].x - q.x;
		p1.y = vert[i].y - q.y;
		p1.z = vert[i].z - q.z;
		p2.x = vert[(i+1)%vert.size()].x - q.x;
		p2.y = vert[(i+1)%vert.size()].y - q.y;
		p2.z = vert[(i+1)%vert.size()].z - q.z;

		m1 = sqrt(p1.x*p1.x + p1.y*p1.y + p1.z*p1.z);
		m2 = sqrt(p2.x*p2.x + p2.y*p2.y + p2.z*p2.z);
		if (m1*m2 <= e)
			return(true); /* siamo su un vertice */
		else
			costheta = (p1.x*p2.x + p1.y*p2.y + p1.z*p2.z) / (m1*m2);
		// prevengo possibili errori di approssimazione
		if(costheta<-1.0)
			costheta = -1.0;
		else if(costheta>1.0)
			costheta = 1.0;

		anglesum += acos(costheta);
	}
	if(abs(6.283185307179586476925287 - anglesum) <= e){
		printf("punto (%g %g %g) è in\n",q.x,q.y,q.z);
		return true;
	}
	else{
		printf("punto (%g %g %g) è out\n",q.x,q.y,q.z);
		return false;
	}
}

/* Verifica se un punto è interno a un poligono (concavo o convesso) */
bool gen_pnpoly(Mod_SubdivMesh *mesh, int f, Vertex v){
  
  // triangolarizzo il poligono virtualmente, di modo da ottenere solo facce convesse
  int **triangles;
  int i, nTriangles;
  vector<Vertex> poly;
  Vertex v1, v2, v3;  /* vertici del triangolo */
  bool test;

  nTriangles = 0;
  test = false;

  if (mesh->face[f].nVert == 3) { /* la face è triangolare */

	  v1.x = mesh->vert[mesh->face[f].vert[0]].x;
	  v1.y = mesh->vert[mesh->face[f].vert[0]].y;
	  v1.z = mesh->vert[mesh->face[f].vert[0]].z;
	  v2.x = mesh->vert[mesh->face[f].vert[1]].x;
	  v2.y = mesh->vert[mesh->face[f].vert[1]].y;
	  v2.z = mesh->vert[mesh->face[f].vert[1]].z;
	  v3.x = mesh->vert[mesh->face[f].vert[2]].x;
	  v3.y = mesh->vert[mesh->face[f].vert[2]].y;
	  v3.z = mesh->vert[mesh->face[f].vert[2]].z;

	  poly.push_back(v1);
	  poly.push_back(v2);
	  poly.push_back(v3);

	  // printf("Controllo se il punto (%g %g %g) è in (%g %g %g)(%g %g %g)(%g %g %g)\n",v.x,v.y,v.z,v1.x,v1.y,v1.z,v2.x,v2.y,v2.z,v3.x,v3.y,v3.z);
	  test = gen_pointDplane2DV(v,poly,0.000002);

	  if(!test){
		  // verifico se appartiene a uno dei lati
		  for(int t=0;t<3;t++){
			  test = gen_pointDsegment(v,poly[t],poly[(t+1)%3],0.000002);
			  if(test) break;
		  }
	  }

  } else { /* la face è un poligono da triangolarizzare */

	  triangles = gen_triangulationPoly(mesh, f, &nTriangles);

	  for (i=0; i < nTriangles; i++) {

		  v1.x = mesh->vert[triangles[i][0]].x;
		  v1.y = mesh->vert[triangles[i][0]].y;
		  v1.z = mesh->vert[triangles[i][0]].z;
		  v2.x = mesh->vert[triangles[i][1]].x;
		  v2.y = mesh->vert[triangles[i][1]].y;
		  v2.z = mesh->vert[triangles[i][1]].z;
		  v3.x = mesh->vert[triangles[i][2]].x;
		  v3.y = mesh->vert[triangles[i][2]].y;
		  v3.z = mesh->vert[triangles[i][2]].z;

		  poly.push_back(v1);
		  poly.push_back(v2);
		  poly.push_back(v3);

		  printf("Controllo se il punto (%g %g %g) è in (%g %g %g)(%g %g %g)(%g %g %g)\n",v.x,v.y,v.z,v1.x,v1.y,v1.z,v2.x,v2.y,v2.z,v3.x,v3.y,v3.z);
		  test = gen_pointDplane2DV(v,poly,0.000002);

		  if(!test){
			  // verifico se appartiene a uno dei lati
			  for(int t=0;t<3;t++){
				  test = gen_pointDsegment(v,poly[t],poly[(t+1)%3],0.000002);
				  if(test) break;
			  }
		  }

		  if (test) break;

		  poly.clear();
	  }
  }

  if (nTriangles) {
	  for (i=0; i < nTriangles; i++) {
		  free(triangles[i]);
	  }
	  free(triangles);
  }

  return test;

}

/* Funzione che determina se la distanza di un punto da una face,
   definita dai suoi vertici non complanari, rientra in un valore
   di tolleranza. */
bool gen_pointDiperPlane(Vertex P, Mod_SubdivMesh *mesh, int f, float e) {

	int i, k;
	double a, b, c, d, t, dBP, m;
	double B2d[2], P2d[2], V2d1[2], V2d2[2], I[2];
	char elim;
	Vector aa, bb, cc, vNormal, fNormal, *hv;
	bool test;

	test = true;
	m = 0;

	/* Prima Fase: si determina la normale della face, come media delle
                 normali di ogni vertex. */
	k = mesh->face[f].nVert;
	fNormal.x = 0;  fNormal.y = 0;  fNormal.z = 0;

	for (i=0; i < k; i++) {

		aa.x = mesh->vert[mesh->face[f].vert[(i + 1) % k]].x;
		aa.y = mesh->vert[mesh->face[f].vert[(i + 1) % k]].y;
		aa.z = mesh->vert[mesh->face[f].vert[(i + 1) % k]].z;
		bb.x = mesh->vert[mesh->face[f].vert[i]].x;
		bb.y = mesh->vert[mesh->face[f].vert[i]].y;
		bb.z = mesh->vert[mesh->face[f].vert[i]].z;
		cc.x = mesh->vert[mesh->face[f].vert[(i + (k - 1)) % k]].x;
		cc.y = mesh->vert[mesh->face[f].vert[(i + (k - 1)) % k]].y;
		cc.z = mesh->vert[mesh->face[f].vert[(i + (k - 1)) % k]].z;

		vector<Vector> triangle;
		triangle.push_back(aa);
		triangle.push_back(bb);
		triangle.push_back(cc);
		vNormal = mat_computeNormal(triangle);

		fNormal.x += vNormal.x;
		fNormal.y += vNormal.y;
		fNormal.z += vNormal.z;
	}
	fNormal.x /= k;
	fNormal.y /= k;
	fNormal.z /= k;

	/* Seconda Fase: si determina il piano passante per P,
                   perpendicolare alla normale della face. */
	a = fNormal.x;
	b = fNormal.y;
	c = fNormal.z;
	d = -(a * P.x) - (b * P.y) - (c * P.z);

	/* Terza Fase: per ciascun vertex della face, si determina
                 la distanza dal piano definito.
                 Contestualmente si tiene nota della proiezione dei
                 vertici sul piano, per poter controllare se il punto P
                 è interno al poligono così definito. */
	hv = (Vector *)malloc(k * sizeof(Vector));  /* proiezione dei vertici */
	if (!hv) ErrorMessage();
	bb.x = 0;  bb.y = 0;  bb.z = 0;  /* baricentro del poligono proiettato */

	for (i=0; i < k; i++) {

		aa.x = mesh->vert[mesh->face[f].vert[i]].x;
		aa.y = mesh->vert[mesh->face[f].vert[i]].y;
		aa.z = mesh->vert[mesh->face[f].vert[i]].z;

		/* si determina il parametro t della retta r, perpendicolare al piano e
       passante di volta in volta per uno dei vertici, nell'intersezione con
       il piano: (ax0 + by0 + cz0 + d) + (al + bm + cn)t = 0
       e di conseguenza il punto di intersezione. */
		t = -(a*aa.x + b*aa.y + c*aa.z + d)/(a*a + b*b + c*c);
		hv[i].x = aa.x + a * t;
		hv[i].y = aa.y + b * t;
		hv[i].z = aa.z + c * t;

		bb.x += hv[i].x;  bb.y += hv[i].y;  bb.z += hv[i].z;

		/* è possibile calcolare ora la distanza del vertex dal piano ... */
		m += sqrt(pow((aa.x - hv[i].x), 2) + pow((aa.y - hv[i].y), 2) +
				pow((aa.z - hv[i].z), 2));
	}
	/* baricentro del poligono proiettato */
	bb.x = bb.x / k;  bb.y = bb.y / k;  bb.z = bb.z / k;

	/* Quarta Fase: si determina se il punto P è interno al poligono proiettato,
                  anche in qusto caso si procede riportandosi in 2D. */
	/* eliminazione coordinata del baricentro e della proiezione */
	if ( fabs(fNormal.x) >= fabs(fNormal.y) &&
			fabs(fNormal.x) >= fabs(fNormal.z) ) {

		elim = X;
		B2d[0] = bb.y;  B2d[1] = bb.z;
		P2d[0] = P.y;   P2d[1] = P.z;

	} else if (fabs(fNormal.y) >= fabs(fNormal.x) &&
			fabs(fNormal.y) >= fabs(fNormal.z)) {

		elim = Y;
		B2d[0] = bb.x;  B2d[1] = bb.z;
		P2d[0] = P.x;   P2d[1] = P.z;

	} else {
		elim = Z;
		B2d[0] = bb.x;  B2d[1] = bb.y;
		P2d[0] = P.x;   P2d[1] = P.y;
	}
	/* distanza di P dal Baricentro del poligono proiettato */
	dBP = sqrt(pow((B2d[0] - P2d[0]), 2) + pow((B2d[1] - P2d[1]), 2));

	/* controllo delle intersezioni con gli edge */
	for (i=0; i < k; i++) {

		switch (elim) { /* eliminazione coordinata dell'edge proiettato */
		case X:
			V2d1[0] = hv[i].y;
			V2d1[1] = hv[i].z;
			V2d2[0] = hv[(i + 1) % k].y;
			V2d2[1] = hv[(i + 1) % k].z;
			break;
		case Y:
			V2d1[0] = hv[i].x;
			V2d1[1] = hv[i].z;
			V2d2[0] = hv[(i + 1) % k].x;
			V2d2[1] = hv[(i + 1) % k].z;
			break;
		default:
			V2d1[0] = hv[i].x;
			V2d1[1] = hv[i].y;
			V2d2[0] = hv[(i + 1) % k].x;
			V2d2[1] = hv[(i + 1) % k].y;
			break;
		}

		/* intersezione tra la retta per BP (baricentro e punto) e
       vertici proiettati: se il determinante è uguale 0 le rette sono
       parallele, altrimenti si verifica l'intersezione */
		d = (P2d[0] - B2d[0]) * (-V2d2[1] + V2d1[1]) -
				((-V2d2[0] + V2d1[0]) * (P2d[1] - B2d[1]));

		if (d) {

			/* si determina il parametro t per l'intersezione su BP ... */
			t = 1/d * ( (V2d1[0] - B2d[0]) * (-V2d2[1] + V2d1[1]) -
					((-V2d2[0] + V2d1[0]) * (V2d1[1] - B2d[1])) );

			/* ... e il relativo punto di intersezione */
			I[0] = B2d[0] + (P2d[0] - B2d[0]) * t;
			I[1] = B2d[1] + (P2d[1] - B2d[1]) * t;

			/* è possibile determinare la distanza BI */
			d = sqrt(pow((I[0] - B2d[0]), 2) + pow((I[1] - B2d[1]), 2));

			if ( (d + e) < dBP) { /* se l'intersezione è "più vicina" si verifica
                               che sia esterna all'edge e al segmento BP */

				if ( ((MINOR(B2d[0],P2d[0]) <= I[0] && I[0] <= MAJOR(B2d[0],P2d[0])) &&
						(MINOR(B2d[1],P2d[1]) <= I[1] && I[1] <= MAJOR(B2d[1],P2d[1]))) &&
						((MINOR(V2d1[0],V2d2[0]) <= I[0] && I[0] <= MAJOR(V2d1[0],V2d2[0])) &&
								(MINOR(V2d1[1],V2d2[1]) <= I[1] && I[1] <= MAJOR(V2d1[1],V2d2[1]))) ) {
					test = false;
					return test;
				}
			}
		}
	}

	/* Ultima fase: si controlla se la media delle distanze rientra
                  nella tolleranza richiesta. */
	m = m / k;
#if DEBUG_GLUE
	printf("Average Distance: %g ",m);
#endif
	if (m > e) test = false;

	return test;
}

/* Procedura di ristrutturazione della mesh, vengono eliminati
   i vertici ridondanti.
   ATTENZIONE: in alcuni casi questa attività è da svolgersi prima
               della chimata alla procedura LoadSubdivMesh(). */
Mod_SubdivMesh* gen_collapseVmiss(Mod_SubdivMesh *mesh, float toll, bool onlyBound) {

	int i, j, k;
	Mod_SubdivMesh *new_mesh;
	int *vneigh, *copy_vn;

	/* Individuazione vertici duplicati */
	/* l'indice 0 rimane inutilizzato */
	vneigh = (int*)calloc((mesh->nVert + 1), sizeof(int));
	copy_vn = (int*)calloc((mesh->nVert + 1), sizeof(int));
	if (!vneigh || !copy_vn) ErrorMessage();

#if DEBUG_GLUE
	printf("COLLAPSE---------------------------->>\n");
#endif

	for (i=1; i <= mesh->nVert; i++) {
		if (onlyBound && mesh->vert[i].bound) { /* Per l'unione di patch
                                               di un singolo obj */
			for (j=1; j <= mesh->nVert; j++) {
				if (mesh->vert[j].bound &&
						fabs(mesh->vert[i].x - mesh->vert[j].x) < toll &&
						fabs(mesh->vert[i].y - mesh->vert[j].y) < toll &&
						fabs(mesh->vert[i].z - mesh->vert[j].z) < toll) {
					if (i!=j && !vneigh[i]) {
						vneigh[j] = copy_vn[j] = i;
#if DEBUG_GLUE
						printf("Find: vertex repeat vertex (%d,%d)\n",i,j);
#endif
					}
				}
			}
		} else if (!onlyBound) {

			for (j=1; j <= mesh->nVert; j++) {
				if (fabs(mesh->vert[i].x - mesh->vert[j].x) < toll &&
						fabs(mesh->vert[i].y - mesh->vert[j].y) < toll &&
						fabs(mesh->vert[i].z - mesh->vert[j].z) < toll) {
					if (i!=j && !vneigh[i]) {
						vneigh[j] = copy_vn[j] = i;
#if DEBUG_GLUE
						printf("Find: vertex repeat vertex (%d,%d)\n",i,j);
#endif
					}
				}
			}
		}
	}

	/* Rimappatura vertici: vneigh conterrà la nuova indicizzazioine,
                          copy_vn servirà per rimappare i vertici doppi. */
	j = 1;  k = 0;
	for (i=1; i <= mesh->nVert; i++) {
		if (!vneigh[i]) { vneigh[i] = j++; k++; }
		else vneigh[i] = 0;
	}

	/* Eliminazione vertici ridondanti */
	new_mesh = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
	if (!new_mesh) ErrorMessage();
	new_mesh->nVert = k;
	new_mesh->nFace = mesh->nFace;
	new_mesh->vert  = (Vertex*) malloc((new_mesh->nVert + 1) * sizeof(Vertex));
	if (!new_mesh->vert) ErrorMessage();
	new_mesh->face = (Face*) malloc((new_mesh->nFace + 1) * sizeof(Face));
	if (!new_mesh->face) ErrorMessage();

	/* ... conservazione vertici singoli ... */
	for (i=1; i <= mesh->nVert; i++) {
#if DEBUG_GLUE
		if (i==1) printf("Nuova lista vertici:\n");
#endif
		if (vneigh[i]) {
			new_mesh->vert[vneigh[i]].x = mesh->vert[i].x;
			new_mesh->vert[vneigh[i]].y = mesh->vert[i].y;
			new_mesh->vert[vneigh[i]].z = mesh->vert[i].z;

#if DEBUG_GLUE
			printf("%f %f %f\n",new_mesh->vert[vneigh[i]].x,
					new_mesh->vert[vneigh[i]].y,
					new_mesh->vert[vneigh[i]].z);
#endif
		}
	}

	/* ... rimappatura dei vertici delle faccette, con controllo per il cambio
     della valenza nel caso di vertici doppi in una faccia dovuti
     alla rimappatura. */
	for (i=1; i <= mesh->nFace; i++) {

		new_mesh->face[i].nVert = mesh->face[i].nVert;
#if DEBUG_GLUE
		if (i==1) printf("Nuova lista facce:\n");
		printf("Face no.%d  NVertices %d  Vertices ",i,mesh->face[i].nVert);
#endif

		for (k=0; k < mesh->face[i].nVert; k++) {

			if (!copy_vn[mesh->face[i].vert[k]])
				new_mesh->face[i].vert[k] = vneigh[mesh->face[i].vert[k]];
			else
				new_mesh->face[i].vert[k] = vneigh[copy_vn[mesh->face[i].vert[k]]];

#if DEBUG_GLUE
			printf("%d ",new_mesh->face[i].vert[k]);
#endif
		}

#if DEBUG_GLUE
		printf("\n");
#endif
	}

#if DEBUG_GLUE
	printf("<<----------------------------COLLAPSE\n");
#endif

	new_mesh = gen_eraseRepeatVinF(new_mesh);

	free(mesh->vert);
	free(mesh->edge);
	free(mesh->face);
	free(mesh);
	free(vneigh);
	free(copy_vn);

	return new_mesh;
}

/* Procedura di ristrutturazione della mesh, vengono eliminati
   i vertici inutilizzati. */
Mod_SubdivMesh* gen_eraseVmiss(Mod_SubdivMesh *mesh) {

	int i, j, k;
	Mod_SubdivMesh *new_mesh;
	int *vneigh;

	/* Individuazione vertici inutilizzati */
	/* l'indice 0 rimane inutilizzato */
	vneigh = (int*)calloc((mesh->nVert + 1), sizeof(int));
	if (!vneigh) ErrorMessage();

#if DEBUG_GLUE
	printf("ERASE V-------------------------->>\n");
#endif

	for (i=1; i <= mesh->nFace; i++)
		for (j=0; j < mesh->face[i].nVert; j++)
			vneigh[mesh->face[i].vert[j]] = mesh->face[i].vert[j];

	j = 0;
	for (i=1; i <= mesh->nVert; i++)
		if (!vneigh[i]) {
			j++;
#if DEBUG_GLUE
			printf("Find unused vertex %d %d\n",i,vneigh[i]);
#endif
		}

	/* Eliminazione vertici inutilizzati */
	new_mesh = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
	if (!new_mesh) ErrorMessage();
	new_mesh->nVert = mesh->nVert - j;
	new_mesh->nFace = mesh->nFace;
	new_mesh->vert  = (Vertex*) malloc((new_mesh->nVert + 1) * sizeof(Vertex));
	if (!new_mesh->vert) ErrorMessage();
	new_mesh->face = (Face*) malloc((new_mesh->nFace + 1) * sizeof(Face));
	if (!new_mesh->face) ErrorMessage();

	/* rimappatura vertici: le coordinate vanno recuperate dalla
     mesh vecchia usando i vecchi indici, ma vanno memorizzate
     nella mesh nuova con i nuovi indici. */
	j = 1;
	for (i=1; i <= mesh->nVert; i++)
		if (vneigh[i]) vneigh[i] = j++;

	/* ... copia dei vertici e ... */
	for (i=1; i <= mesh->nVert; i++) {

#if DEBUG_GLUE
		if (i==1) printf("Nuova lista vertici:\n");
#endif

		if (vneigh[i]) {
			new_mesh->vert[vneigh[i]].x = mesh->vert[i].x;
			new_mesh->vert[vneigh[i]].y = mesh->vert[i].y;
			new_mesh->vert[vneigh[i]].z = mesh->vert[i].z;

#if DEBUG_GLUE
			printf("%f %f %f\n",new_mesh->vert[vneigh[i]].x,
					new_mesh->vert[vneigh[i]].y,
					new_mesh->vert[vneigh[i]].z);
#endif
		}
	}

	/* ... copia delle faccette. */
	for (i=1; i <= mesh->nFace; i++) {

		new_mesh->face[i].nVert = mesh->face[i].nVert;
#if DEBUG_GLUE
		if (i==1) printf("Nuova lista facce:\n");
		printf("Face no.%d  NVertices %d  Vertices ",i,mesh->face[i].nVert);
#endif

		for (k=0; k < mesh->face[i].nVert; k++) {
			new_mesh->face[i].vert[k] = vneigh[mesh->face[i].vert[k]];
#if DEBUG_GLUE
			printf("%d ",new_mesh->face[i].vert[k]);
#endif
		}

#if DEBUG_GLUE
		printf("\n");
#endif
	}

#if DEBUG_GLUE
	printf("<<--------------------------V ERASE\n");
#endif

	new_mesh->mod_LoadSubdivMesh();

	free(mesh->vert);
	free(mesh->edge);
	free(mesh->face);
	free(mesh);
	free(vneigh);

	return new_mesh;
}

/* Procedura di ristrutturazione della mesh, viene cambiata la valenza alle
   faccette che presentano vertici uguali ripetuti. */
Mod_SubdivMesh* gen_eraseRepeatVinF(Mod_SubdivMesh *mesh) {

	int i, k, nk;
	Mod_SubdivMesh *new_mesh;

	new_mesh = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
	if (!new_mesh) ErrorMessage();
	new_mesh->nVert = mesh->nVert;
	new_mesh->nFace = mesh->nFace;
	new_mesh->vert  = (Vertex*) malloc((new_mesh->nVert + 1) * sizeof(Vertex));
	if (!new_mesh->vert) ErrorMessage();
	new_mesh->face = (Face*) malloc((new_mesh->nFace + 1) * sizeof(Face));
	if (!new_mesh->face) ErrorMessage();

	/* copia dei vertici */
	for (k=1; k <= mesh->nVert; k++) {
		new_mesh->vert[k].x = mesh->vert[k].x;
		new_mesh->vert[k].y = mesh->vert[k].y;
		new_mesh->vert[k].z = mesh->vert[k].z;
		new_mesh->vert[k].ins = mesh->vert[k].ins;
		new_mesh->vert[k].tan = mesh->vert[k].tan;
	}

	/* copia con relativo controllo delle faccette */
	for (i=1; i <= mesh->nFace; i++) {

		nk = 0;

		for (k=0; k < mesh->face[i].nVert; k++) {

			if ( mesh->face[i].vert[k] ==
					mesh->face[i].vert[((k+mesh->face[i].nVert-1)%(mesh->face[i].nVert))]
			) {
#if DEBUG_GLUE
				if ((k-nk) >= 1) printf("\n");
				printf("New valence for face n° %d: ",i);
#endif

			} else {
				new_mesh->face[i].vert[nk] = mesh->face[i].vert[k];
				nk += 1;
			}
		}
		if (nk != k) {
			new_mesh->face[i].nVert = mesh->face[i].nVert - (k-nk);
#if DEBUG_GLUE
			printf(" %d\n",new_mesh->face[i].nVert);
#endif
		} else new_mesh->face[i].nVert = mesh->face[i].nVert;

		new_mesh->face[i].tan = mesh->face[i].tan;

	}

	new_mesh->mod_LoadSubdivMesh();


	return new_mesh;
}

/* Procedura per la ricerca delle intersezioni tra
   edge e face di due differenti mesh. */
q_point* gen_edgeIntersectFace(Mod_SubdivMesh *mesh_1, Mod_SubdivMesh *mesh_2) {

	int i, j;
	Vertex P1, P2, I;
	q_point *intersectionP, *tmp;

	intersectionP = NULL;  tmp = NULL;

	/* Ricerca dei punti di intersezione */
	for (i=1; i <= mesh_1->nEdge; i++) {

		P1.x = mesh_1->vert[mesh_1->edge[i].vert[0]].x;
		P1.y = mesh_1->vert[mesh_1->edge[i].vert[0]].y;
		P1.z = mesh_1->vert[mesh_1->edge[i].vert[0]].z;
		P2.x = mesh_1->vert[mesh_1->edge[i].vert[1]].x;
		P2.y = mesh_1->vert[mesh_1->edge[i].vert[1]].y;
		P2.z = mesh_1->vert[mesh_1->edge[i].vert[1]].z;

		for (j=1; j <= mesh_2->nFace; j++) {

			if(mesh_2->face[j].bb == 0) continue;

			if (gen_segmentCrossPolygon(mesh_2, j, P1, P2, &I)) {

				if (intersectionP == NULL) {
					intersectionP = (q_point*) malloc(sizeof(q_point));
					if (!intersectionP) ErrorMessage();
					intersectionP->next = NULL;
					tmp = intersectionP;
				} else {
					tmp->next = (q_point*) malloc(sizeof(q_point));
					if (!tmp->next) ErrorMessage();
					tmp = tmp->next;
					tmp->next = NULL;
				}
				tmp->v.x = I.x;
				tmp->v.y = I.y;
				tmp->v.z = I.z;
				tmp->indexFace = j;
				tmp->indexEdge = i;
			}
		}
	}

	return intersectionP;
}

/* Procedura che individua il punto di intersezione
   tra un segmento e una face definita da un piano. */
bool gen_segmentCrossPolygon(Mod_SubdivMesh *mesh, int f, Vertex P, Vertex Q, Vertex *C) {

	int **triangles;
	int i, nTriangles;
	Vector v1, v2, v3;  /* vertici del triangolo */
	Vector r, s;        /* estremi del segmento */
	Vector cT, cS;      /* punto di intersezione nel triangolo e nel segmento */
	bool testCross;

	nTriangles = 0;
	r.x = P.x;  r.y = P.y;  r.z = P.z;
	s.x = Q.x;  s.y = Q.y;  s.z = Q.z;

	if (mesh->face[f].nVert == 3) { /* la face è triangolare */

		v1.x = mesh->vert[mesh->face[f].vert[0]].x;
		v1.y = mesh->vert[mesh->face[f].vert[0]].y;
		v1.z = mesh->vert[mesh->face[f].vert[0]].z;
		v2.x = mesh->vert[mesh->face[f].vert[1]].x;
		v2.y = mesh->vert[mesh->face[f].vert[1]].y;
		v2.z = mesh->vert[mesh->face[f].vert[1]].z;
		v3.x = mesh->vert[mesh->face[f].vert[2]].x;
		v3.y = mesh->vert[mesh->face[f].vert[2]].y;
		v3.z = mesh->vert[mesh->face[f].vert[2]].z;

		mat_intersection(&v1, &v2, &v3, &r, &s, &cT, &cS, &testCross);

	} else { /* la face è un poligono da triangolarizzare */

		triangles = gen_triangulationPoly(mesh, f, &nTriangles);

		for (i=0; i < nTriangles; i++) {

			v1.x = mesh->vert[triangles[i][0]].x;
			v1.y = mesh->vert[triangles[i][0]].y;
			v1.z = mesh->vert[triangles[i][0]].z;
			v2.x = mesh->vert[triangles[i][1]].x;
			v2.y = mesh->vert[triangles[i][1]].y;
			v2.z = mesh->vert[triangles[i][1]].z;
			v3.x = mesh->vert[triangles[i][2]].x;
			v3.y = mesh->vert[triangles[i][2]].y;
			v3.z = mesh->vert[triangles[i][2]].z;

			mat_intersection(&v1, &v2, &v3, &r, &s, &cT, &cS, &testCross);

			if (testCross) break;

		}
	}

	if (testCross) {

		C->x = cS.x;
		C->y = cS.y;
		C->z = cS.z;

#if DEBUG_GLUE
		if (nTriangles) {
			printf("Intersection in: %g %g %g with triangle: %d %d %d\n",
					C->x, C->y, C->z, triangles[i][0],triangles[i][1],triangles[i][2]);
		} else {
			printf("Intersection in: %g %g %g with triangle: %d %d %d\n",C->x,C->y,C->z,
					mesh->face[f].vert[0],mesh->face[f].vert[1],mesh->face[f].vert[2]);
		}
#endif
	}
	
	if (nTriangles) {
		for (i=0; i < nTriangles; i++) {
			free(triangles[i]);
		}
		free(triangles);
	}

	return testCross;
}

/* Procedura che suddivide una face triangolare della mesh. */
void gen_splitTriangleFace(Mod_SubdivMesh *mesh, int f) {

	int i, j, nv, nf, nface;
	int triangles[6];
	Vertex newP;
	Vertex *new_vert;
	Face *new_face;

	gen_splitTriangle(mesh, f, &newP, triangles);

	/* Nuovi vertici */
	nv = mesh->nVert + 1;  /* old face + new triangles - face split */
	new_vert = (Vertex*) malloc((nv + 1) * sizeof(Vertex));
	if (!new_vert) ErrorMessage();
	for (i=1; i <= mesh->nVert; i++) {
		new_vert[i].x = mesh->vert[i].x;
		new_vert[i].y = mesh->vert[i].y;
		new_vert[i].z = mesh->vert[i].z;
	}
	new_vert[nv].x = newP.x;
	new_vert[nv].y = newP.y;
	new_vert[nv].z = newP.z;

	triangles[2] = nv;
	triangles[4] = nv;


	/* Nuove face */
	nface = mesh->nFace + 1;
	new_face = (Face*) malloc((nface + 1) * sizeof(Face));
	if (!new_face) ErrorMessage();

	nf = 1;
	for (i=1; i <= mesh->nFace; i++) {

		if (i!=f) {
			new_face[nf].nVert = mesh->face[i].nVert;
			new_face[nf].pointInto = 0;
			new_face[nf].tan = mesh->face[i].tan;
			new_face[nf].bb = mesh->face[i].bb;

			for (j=0; j < mesh->face[i].nVert; j++)
				new_face[nf].vert[j] = mesh->face[i].vert[j];

			nf++;

		} else {

			new_face[nf].nVert = 3;
			new_face[nf].pointInto = 0;

			for (j=0; j < 3; j++)
				new_face[nf].vert[j] = triangles[j];

			nf++;

			new_face[nf].nVert = 3;
			new_face[nf].pointInto = 0;

			for (j=3; j < 6; j++)
				new_face[nf].vert[(j-3)] = triangles[j];

			nf++;

		}
	}

	free(mesh->vert);
	mesh->nVert = nv;
	mesh->vert = new_vert;

	free(mesh->face);
	mesh->nFace = nface;
	mesh->face = new_face;

	mesh->mod_LoadSubdivMesh();

	return;
}

/* Procedura che triangolarizza una face della mesh. */
int gen_triangulationOneFace(Mod_SubdivMesh *mesh, int f) {

	int i, j, k, nf, nTri, nface;
	int **triangles;
	Face *new_face;


	triangles = gen_triangulationPoly(mesh, f, &nTri);

	/* Nuove face */
	nface = mesh->nFace + nTri - 1;  /* old face + new triangles - face split */
	new_face = (Face*) malloc((nface + 1) * sizeof(Face));
	if (!new_face) ErrorMessage();

	nf = 1;
	for (i=1; i <= mesh->nFace; i++) {

		if (i!=f) {
			new_face[nf].nVert = mesh->face[i].nVert;
			new_face[nf].pointInto = 0;
			new_face[nf].tan = mesh->face[i].tan;
			new_face[nf].bb = mesh->face[i].bb;

			for (j=0; j < mesh->face[i].nVert; j++)
				new_face[nf].vert[j] = mesh->face[i].vert[j];

			nf++;

		} else {

			for (k=0; k < nTri; k++) {
				new_face[nf].nVert = 3;
				new_face[nf].pointInto = 0;

				for (j=0; j < 3; j++)
					new_face[nf].vert[j] = triangles[k][j];

				nf++;
			}
		}
	}

	free(mesh->face);
	mesh->nFace = nface;
	mesh->face = new_face;

	mesh->mod_LoadSubdivMesh();

	for (k=0; k < nTri; k++) {
		free(triangles[k]);
	}
	free(triangles);

	// ritorno il numero di nuove facce inserite a partire dalla faccia f
	return nTri;
}

/* Funzione che effettua una triangolarizzazione virtuale di un poligono. */
int** gen_triangulationPoly(Mod_SubdivMesh *m, int f, int *nTri) {

	int i, j, k, mod;
	int *vconc;
	int **tri;
	bool tC, consT;
	Mod_SubdivMesh *workM;
	struct T_QUEUE {
		int vert[3];
		struct T_QUEUE *next;
	} *trg, *tmpT;

	*nTri = 0;
	workM = NULL;  trg = NULL;  tmpT = NULL;
	mod = m->face[f].nVert;

	vconc = gen_shapeFace(m, f, &tC);

	if (tC) { /* Face convessa */

		*nTri = mod - 2;

		/* Una triangolarizzazione banale prevede di prendere
       come riferimento il primo vertice, quello sarà il vertice
       di ogni triangolo costruito con gli altri punti della face.
       In particolare saranno prodotti n-2 triangolo, con
       n = numero_vertici_della_face. */
		tri = (int**) malloc(*nTri * sizeof(int));
		if (!tri) ErrorMessage();

		for (i=0; i < *nTri; i++) {
			tri[i] = (int *) calloc(3, sizeof(int));
			if (!tri[i]) ErrorMessage();
			else {
				tri[i][0] = m->face[f].vert[0];
				tri[i][1] = m->face[f].vert[(i+1)%mod];
				tri[i][2] = m->face[f].vert[(i+2)%mod];
			}
		}

	} else { /* Face concava */

		/* viene creata una copia di lavoro della face */
		workM = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
		if (!workM) ErrorMessage();
		workM->nVert = m->nVert;
		workM->nFace = 1;
		workM->vert  = (Vertex*) malloc((workM->nVert + 1) * sizeof(Vertex));
		if (!workM->vert) ErrorMessage();
		workM->face = (Face*) malloc((workM->nFace + 1) * sizeof(Face));
		if (!workM->face) ErrorMessage();
		/* ... copia lavoro dei vertici e ... */
		for (i=1; i <= workM->nVert; i++) {
			workM->vert[i].x = m->vert[i].x;
			workM->vert[i].y = m->vert[i].y;
			workM->vert[i].z = m->vert[i].z;
		}
		/* ... copia lavoro della face. */
		workM->face[1].nVert = m->face[f].nVert;
		for (i=0; i < workM->face[1].nVert; i++) {
			workM->face[1].vert[i] = m->face[f].vert[i];
		}

		/* creazione triangoli sino a che la face è concava */
		do {

			/* allocazione nuovo triangolo */
			if (!trg) {
				trg = (struct T_QUEUE*) malloc(sizeof(struct T_QUEUE));
				if (!trg) ErrorMessage();
				tmpT = trg;
			} else {
				tmpT->next = (struct T_QUEUE*) malloc(sizeof(struct T_QUEUE));
				if (!tmpT->next) ErrorMessage();
				tmpT = tmpT->next;
			}
			tmpT->next = NULL;

			/* il trinagolo non deve essere formato da due vertici consecutivi
         entrambi causa della concavità, quindi si ricerca dal primo ... */
			j = -1;
			do {
				consT = false;
				j++;
				i=0;
				while (workM->face[1].vert[i] != vconc[j]) { i = (i+1) % mod; }
				for (k=0; k < mod; k++) {
					if (vconc[k] && (vconc[k] == workM->face[1].vert[(i+1)%mod]) )
						consT = true;
				}
			} while (consT);

			/* creazione triangolo */
			tmpT->vert[0] = vconc[j];
			tmpT->vert[1] = workM->face[1].vert[(i+1)%mod];
			tmpT->vert[2] = workM->face[1].vert[(i+2)%mod];
			*nTri += 1;

			/* ora è posssibile eliminare dalla face di lavoro il vertice mediano */
			k = (i + 1) % mod;
			for (i=(k+1); i < mod; i++) {
				workM->face[1].vert[k] = workM->face[1].vert[i];
				k++;
			}
			workM->face[1].nVert -= 1;
			mod--;

			free(vconc);
			workM->mod_LoadSubdivMesh();
			vconc = gen_shapeFace(workM, 1, &tC);

		} while ( mod > 3 && !tC);

		/* al termine rimane o un singolo triangolo, o un poligono convesso
       triangolarizzabile in maniera banale */
		if (mod == 3) {
			tmpT->next = (struct T_QUEUE*) malloc(sizeof(struct T_QUEUE));
			if (!tmpT->next) ErrorMessage();
			tmpT = tmpT->next;
			tmpT->next = NULL;
			tmpT->vert[0] = workM->face[1].vert[0];
			tmpT->vert[1] = workM->face[1].vert[1];
			tmpT->vert[2] = workM->face[1].vert[2];
			*nTri += 1;

		} else {

			*nTri = *nTri + (mod - 2);
			for (k=0; k < (mod - 2); k++) {
				tmpT->next = (struct T_QUEUE*) malloc(sizeof(struct T_QUEUE));
				if (!tmpT->next) ErrorMessage();
				tmpT = tmpT->next;
				tmpT->next = NULL;
				tmpT->vert[0] = workM->face[1].vert[0];
				tmpT->vert[1] = workM->face[1].vert[(k+1)%mod];
				tmpT->vert[2] = workM->face[1].vert[(k+2)%mod];
			}

		}

		/* vengono ricopiati tutti i triangoli nella struttura richiesta */
		tri = (int**) malloc(*nTri * sizeof(int));
		if (!tri) ErrorMessage();
		for (i=0; i < *nTri; i++) {
			tri[i] = (int *) calloc(3, sizeof(int));
			if (!tri[i]) ErrorMessage();
			else {
				tri[i][0] = trg->vert[0];
				tri[i][1] = trg->vert[1];
				tri[i][2] = trg->vert[2];
				tmpT = trg;
				trg = trg->next;
				free(tmpT);
			}
		}

	}

#if DEBUG_GLUE
//	printf("Build %d Triangle:\n",*nTri);
//	for (i=0; i < *nTri; i++) {
//		printf("%d %d %d\n",tri[i][0],tri[i][1],tri[i][2]);
//	}
#endif

	free(vconc);
	if (workM) {
		free(workM->vert);
		free(workM->edge);
		free(workM->face);
		free(workM);
	}

	return tri;
}

/* Funzione che suddivide un triangolo */
void gen_splitTriangle(Mod_SubdivMesh *mesh, int f, Vertex *m, int *index) {

	m->x = (mesh->vert[mesh->face[f].vert[1]].x +
			mesh->vert[mesh->face[f].vert[2]].x) / 2;
	m->y = (mesh->vert[mesh->face[f].vert[1]].y +
			mesh->vert[mesh->face[f].vert[2]].y) / 2;
	m->z = (mesh->vert[mesh->face[f].vert[1]].z +
			mesh->vert[mesh->face[f].vert[2]].z) / 2;

	index[0] = mesh->face[f].vert[0];
	index[1] = mesh->face[f].vert[1];
	index[2] = -1;
	index[3] = mesh->face[f].vert[0];
	index[4] = -1;
	index[5] = mesh->face[f].vert[2];

	return;
}

int gen_countIntersections(Mod_SubdivMesh *m_1, Mod_SubdivMesh *m_2, q_point *EM1_FM2, q_point *EM2_FM1, i_point* TmpD){
	/* Vengono contati i punti di intersezione distinti, formando una lista unica:
     -si controllano tutti i punti della prima coda; */
	int nInt = 1;
	int i;
	bool test1;
	Vertex v,p0,p1;
	q_point *qTmp1,*qTmp2;
	i_point *TmpDT1, *TmpDT2;

	TmpD = (i_point*) malloc(sizeof(i_point));
	if (!TmpD) ErrorMessage();
	TmpD->point = EM1_FM2;
	TmpD->queueMesh = EM1FM2;
	TmpD->next = NULL;
	TmpD->prev = NULL;
	TmpDT1 = TmpD;

	qTmp1 = EM1_FM2->next;
	while (qTmp1) {

		qTmp2 = EM1_FM2;
		do {

			if ( ((float)qTmp2->v.x == (float)qTmp1->v.x) &&
					((float)qTmp2->v.y == (float)qTmp1->v.y) &&
					((float)qTmp2->v.z == (float)qTmp1->v.z)) break;

			qTmp2 = qTmp2->next;
		} while (qTmp2 != qTmp1);

		if (qTmp2 == qTmp1) {
			nInt += 1;
			TmpDT1->next = (i_point*) malloc(sizeof(i_point));
			if (!TmpDT1->next) ErrorMessage();
			TmpDT1 = TmpDT1->next;
			TmpDT1->point = qTmp1;
			TmpDT1->queueMesh = EM1FM2;
			TmpDT1->next = NULL;
			TmpDT1->prev = NULL;
		}

		qTmp1 = qTmp1->next;
	}

	/* -si controllano tutti i punti della seconda coda ... */
	qTmp1 = EM2_FM1;
	while (qTmp1) {

		qTmp2 = EM1_FM2;
		i = 1;
		do { /* ... prima con tutti quelli della prima coda ... */

			if ( ((float)qTmp2->v.x == (float)qTmp1->v.x) &&
					((float)qTmp2->v.y == (float)qTmp1->v.y) &&
					((float)qTmp2->v.z == (float)qTmp1->v.z) ) i = 0;

			qTmp2 = qTmp2->next;
		} while (qTmp2);


		if (i) { /* ... poi, se non è stato trovato un duplicato,
                                con quelli della seconda. */
			qTmp2 = EM2_FM1;
			do {

				if ( ((float)qTmp2->v.x == (float)qTmp1->v.x) &&
						((float)qTmp2->v.y == (float)qTmp1->v.y) &&
						((float)qTmp2->v.z == (float)qTmp1->v.z)) break;

				qTmp2 = qTmp2->next;
			} while (qTmp2 != qTmp1);

			if (qTmp2 == qTmp1) {
				nInt += 1;
				TmpDT1->next = (i_point*) malloc(sizeof(i_point));
				if (!TmpDT1->next) ErrorMessage();
				TmpDT1 = TmpDT1->next;
				TmpDT1->point = qTmp1;
				TmpDT1->queueMesh = EM2FM1;
				TmpDT1->next = NULL;
				TmpDT1->prev = NULL;
			}
		}

		qTmp1 = qTmp1->next;
	}

#if DEBUG_GLUE
	printf("Found %d distinct intersection point,\n",nInt);
	TmpDT1 = TmpD;
	do {
		printf("in: %g %g %g\n",
				TmpDT1->point->v.x, TmpDT1->point->v.y, TmpDT1->point->v.z);
		TmpDT1 = TmpDT1->next;
	} while (TmpDT1);
#endif

	/* Ora è possibile determinare il numero di punti di intersezione distinti,
     interni di ogni face. */
	TmpDT1 = TmpD;
	while (TmpDT1) {

		/* face della mesh 1 da analizzare ... */
		if (TmpDT1->queueMesh == EM2FM1 &&
				m_1->face[TmpDT1->point->indexFace].pointInto == 0) {

			TmpDT2 = TmpD;
			do {
				if ( (TmpDT2->queueMesh == EM2FM1) &&
						(TmpDT2->point->indexFace == TmpDT1->point->indexFace) ) {

					test1 = false;

					v.x = TmpDT2->point->v.x;
					v.y = TmpDT2->point->v.y;
					v.z = TmpDT2->point->v.z;
					/* il punto deve essere interno, viene escluso se su un vertice o su
             un edge della face */
					for (i=0; i < m_1->face[TmpDT1->point->indexFace].nVert; i++) {
						if ( ((float)m_1->vert[m_1->face[TmpDT1->point->indexFace].vert[i]].x ==
								(float)v.x) &&
								((float)m_1->vert[m_1->face[TmpDT1->point->indexFace].vert[i]].y ==
										(float)v.y) &&
										((float)m_1->vert[m_1->face[TmpDT1->point->indexFace].vert[i]].z ==
												(float)v.z) ) { test1 = true; break; }
					}
					for (i=0; i < m_1->face[TmpDT1->point->indexFace].nVert; i++) {
						p0.x = m_1->vert[m_1->edge[m_1->face[TmpDT1->point->indexFace].edge[i]].vert[0]].x;
						p0.y = m_1->vert[m_1->edge[m_1->face[TmpDT1->point->indexFace].edge[i]].vert[0]].y;
						p0.z = m_1->vert[m_1->edge[m_1->face[TmpDT1->point->indexFace].edge[i]].vert[0]].z;
						p1.x = m_1->vert[m_1->edge[m_1->face[TmpDT1->point->indexFace].edge[i]].vert[1]].x;
						p1.y = m_1->vert[m_1->edge[m_1->face[TmpDT1->point->indexFace].edge[i]].vert[1]].y;
						p1.z = m_1->vert[m_1->edge[m_1->face[TmpDT1->point->indexFace].edge[i]].vert[1]].z;
						if (gen_pointDsegment(v, p0, p1, 0)) { test1 = true; break; }
					}

					if (!test1) m_1->face[TmpDT1->point->indexFace].pointInto += 1;
				}

				TmpDT2 = TmpDT2->next;
			} while (TmpDT2);
		}

		TmpDT1 = TmpDT1->next;
	}

	TmpDT1 = TmpD;
	while (TmpDT1) {

		/* face della mesh 2 da analizzare ... */
		if (TmpDT1->queueMesh == EM1FM2 &&
				m_2->face[TmpDT1->point->indexFace].pointInto == 0) {

			TmpDT2 = TmpD;
			do {

				if ( (TmpDT2->queueMesh == EM1FM2) &&
						(TmpDT2->point->indexFace == TmpDT1->point->indexFace) ) {

					test1 = false;
					v.x = TmpDT2->point->v.x;
					v.y = TmpDT2->point->v.y;
					v.z = TmpDT2->point->v.z;
					/* il punto deve essere interno, viene escluso se su un vertice o su
             un edge della face */
					for (i=0; i < m_2->face[TmpDT1->point->indexFace].nVert; i++) {
						if ( ((float)m_2->vert[m_2->face[TmpDT1->point->indexFace].vert[i]].x ==
								(float)v.x) &&
								((float)m_2->vert[m_2->face[TmpDT1->point->indexFace].vert[i]].y ==
										(float)v.y) &&
										((float)m_2->vert[m_2->face[TmpDT1->point->indexFace].vert[i]].z ==
												(float)v.z) ) { test1 = true; break; }
					}
					for (i=0; i < m_2->face[TmpDT1->point->indexFace].nVert; i++) {
						p0.x = m_2->vert[m_2->edge[m_2->face[TmpDT1->point->indexFace].edge[i]].vert[0]].x;
						p0.y = m_2->vert[m_2->edge[m_2->face[TmpDT1->point->indexFace].edge[i]].vert[0]].y;
						p0.z = m_2->vert[m_2->edge[m_2->face[TmpDT1->point->indexFace].edge[i]].vert[0]].z;
						p1.x = m_2->vert[m_2->edge[m_2->face[TmpDT1->point->indexFace].edge[i]].vert[1]].x;
						p1.y = m_2->vert[m_2->edge[m_2->face[TmpDT1->point->indexFace].edge[i]].vert[1]].y;
						p1.z = m_2->vert[m_2->edge[m_2->face[TmpDT1->point->indexFace].edge[i]].vert[1]].z;
						if (gen_pointDsegment(v, p0, p1, 0)) { test1 = true; break; }
					}

					if (!test1) m_2->face[TmpDT1->point->indexFace].pointInto += 1;
				}

				TmpDT2 = TmpDT2->next;
			} while (TmpDT2);
		}

		TmpDT1 = TmpDT1->next;
	}

	return nInt;
}

/* Procedura per la ricostruzione della poligonale definita
   dai punti di intersezione delle due mesh. */
i_point* gen_buildPolygonProfile(Mod_SubdivMesh *m_1, q_point **EM1_FM2,
		Mod_SubdivMesh *m_2, q_point **EM2_FM1, int *count, int *num,
		vector<int>* faceSplit, vector<int>* queueM, int *np, int nTan1, int nTan2) {

	int i, g, h, m, c, flag, onEdge, onFace, inFace, inEdge, prevFace, tmp, tanCount, tanFaceIndex,prevTanFaceIndex;
	int QUEUE; /*, START; */
	int nInt,numTmp;     /* numero di punti di intersezione distinti trovati */
	int ret;
	bool test1,test2,tanFace;
	Vertex v,p0;
	Vertex onPoint;
	q_point *qTmp1,*qTmp2;
	i_point *profile, *iTmp, *riTmp;
	Mod_SubdivMesh *onMesh, *inMesh, *tmpMesh, *mesh;

	/* NB:
	     -on????: indica gli elementi su cui e con cui si sta cercando
	     -in????: indica gli elementi che subiscono le intersezioni da on????
	 */

#if DEBUG_GLUE
	printf("BUILD P---------------------------->>\n");
	/*
	  qTmp1=*EM1_FM2;
	    while(qTmp1!=NULL){
	        printf("Lista EM1_FM2: (%g %g %g ) da edge ( %g %g %g ) ( %g %g %g )\n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z,m_1->vert[m_1->edge[qTmp1->indexEdge].vert[0]].x,m_1->vert[m_1->edge[qTmp1->indexEdge].vert[0]].y,m_1->vert[m_1->edge[qTmp1->indexEdge].vert[0]].z,m_1->vert[m_1->edge[qTmp1->indexEdge].vert[1]].x,m_1->vert[m_1->edge[qTmp1->indexEdge].vert[1]].y,m_1->vert[m_1->edge[qTmp1->indexEdge].vert[1]].z);
	        printf("Indici: edge %d v1 = %d v2 = %d\n",qTmp1->indexEdge,m_1->edge[qTmp1->indexEdge].vert[0],m_1->edge[qTmp1->indexEdge].vert[1]);
	        qTmp1=qTmp1->next;
	    }
	    qTmp1=*EM2_FM1;
	    while(qTmp1!=NULL){
	        printf("Lista EM2_FM1: ( %g %g %g ) da edge ( %g %g %g ) ( %g %g %g )\n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z,m_2->vert[m_2->edge[qTmp1->indexEdge].vert[0]].x,m_2->vert[m_2->edge[qTmp1->indexEdge].vert[0]].y,m_2->vert[m_2->edge[qTmp1->indexEdge].vert[0]].z,m_2->vert[m_2->edge[qTmp1->indexEdge].vert[1]].x,m_2->vert[m_2->edge[qTmp1->indexEdge].vert[1]].y,m_2->vert[m_2->edge[qTmp1->indexEdge].vert[1]].z);
	        printf("Indici: edge %d v1 = %d v2 = %d\n",qTmp1->indexEdge,m_2->edge[qTmp1->indexEdge].vert[0],m_2->edge[qTmp1->indexEdge].vert[1]);
	        qTmp1=qTmp1->next;
	    }
	 */
#endif

	/* RICOSTRUZIONE PROFILO */
	/* Ora è possibile ricostruire il profilo;
	   il punto di partenza non deve essere ambiguo: coincidente con un vertice della face.
	*/
	numTmp = 0;
	*np = 0;
	nInt = *count;
	ret = 0;
	flag = 0;
	if(*EM1_FM2 != NULL){
		qTmp1 = *EM1_FM2;
		QUEUE = EM1FM2;
		mesh = m_1;
	}
	else {
		qTmp1 = *EM2_FM1;
		QUEUE = EM2FM1;
		mesh = m_2;
	}
	do {
		test1 = false;
		onEdge = qTmp1->indexEdge;           /* edge di partenza */

		onFace = mesh->edge[onEdge].neigh[0];    /* una delle face che incide sull'edge */
		for (i=0; i < mesh->face[onFace].nVert; i++) {
			if ( ((float)mesh->vert[mesh->face[onFace].vert[i]].x == (float)qTmp1->v.x) &&
					((float)mesh->vert[mesh->face[onFace].vert[i]].y == (float)qTmp1->v.y) &&
					((float)mesh->vert[mesh->face[onFace].vert[i]].z == (float)qTmp1->v.z) )
				test1 = true;
		}
		// se è un punto di tangenza,verifico se ha solo una faccia in tangenza e che sia il primo o l'ultimo punto della faccia in tangenza
		if(test1 == true && qTmp1->tan == 1 && qTmp1->ins == 1){
			test1 = false;
			tmp = 0;
			i = mesh->mod_find_in_vert(qTmp1->v);
			for(int v=0;v<mesh->vert[i].val;v++){
				if(mesh->face[mesh->vert[i].face[v]].tan==1){
					tmp++;
					m = mesh->vert[i].face[v];
				}
			}
			if(tmp>1){
				test1 = true;
			}
			c = mesh->mod_find_in_face(mesh->face,m,i);
			if(!test1 && !(c==0 || c==mesh->face[m].nVert-1)){
				test1 = true;
			}
		}

		qTmp2 = qTmp1;
		qTmp1 = qTmp1->next;
		if (!qTmp1) break;

	} while (test1);

	if (test1) { /* nel caso si prende un punto di partenza dell'altra coda */

		if(*EM2_FM1 != NULL){
			qTmp1 = *EM2_FM1;
			QUEUE = EM2FM1;
			mesh = m_2;
		}
		else{
			qTmp1 = *EM1_FM2;
			QUEUE = EM1FM2;
			mesh = m_1;
		}
		do {
			test1 = false;
			onEdge = qTmp1->indexEdge;          /* edge di partenza */
			onFace = mesh->edge[onEdge].neigh[0];   /* una delle face che incide sull'edge */
			for (i=0; i < mesh->face[onFace].nVert; i++) {
				if ( ((float)mesh->vert[mesh->face[onFace].vert[i]].x == (float)qTmp1->v.x) &&
						((float)mesh->vert[mesh->face[onFace].vert[i]].y == (float)qTmp1->v.y) &&
						((float)mesh->vert[mesh->face[onFace].vert[i]].z == (float)qTmp1->v.z) )
					test1 = true;
			}
			// se è un punto di tangenza,verifico se ha solo una faccia in tangenza e che sia il primo o l'ultimo punto della faccia in tangenza
			if(test1 == true && qTmp1->tan == 1 && qTmp1->ins == 1){
				test1 = false;
				tmp = 0;
				i = mesh->mod_find_in_vert(qTmp1->v);
				for(int v=0;v<mesh->vert[i].val;v++){
					if(mesh->face[mesh->vert[i].face[v]].tan==1){
						tmp++;
						m = mesh->vert[i].face[v];
					}
				}
				if(tmp>1){
					test1=true;
				}
				c = mesh->mod_find_in_face(mesh->face,m,i);
				if(!test1 && !(c==0 || c==mesh->face[m].nVert-1)){
					test1 = true;
				}
			}

			qTmp2 = qTmp1;
			qTmp1 = qTmp1->next;
			if (!qTmp1) break;

		} while (test1);

	}

	if (test1) {
		printf("Can't start profile with safe point!!\n");
		printf("No profile\n");
		*np = 1;
		// rimuovo tutti i punti dalle liste
		EM1_FM2 = NULL;
		EM2_FM1 = NULL;
		*count = 0;
		*num = *count;
		return NULL;
	}

	/* START = QUEUE;   servirà prima dell'uscita */
	tanFace = false;
	c = 0;
	m = 0;
	/* si inserisce il primo */
	profile = (i_point*) malloc(sizeof(i_point));
	if (!profile) ErrorMessage();
	profile->point = qTmp2;      /* puntatore al punto inserito */
	profile->queueMesh = QUEUE;  /* su quale coda si trova */
	profile->next = NULL;
	profile->prev = NULL;
	iTmp = profile;
	nInt -= 1;
	numTmp++;

	printf("\nPunto iniziale del profilo:  %g %g %g \n",qTmp2->v.x,qTmp2->v.y,qTmp2->v.z);
	/*
	  MORENO
	  Rimuovo il punto inserito dalla lista, prima chiamata --> viene spostato in fondo alla lista
	 */
	//printf("\nLista da cui rimuovo: %d \n",(QUEUE==EM1FM2)?1:2);

	removePoint(qTmp2, EM1_FM2, &flag);
	removePoint(qTmp2, EM2_FM1, &flag);

	onMesh = ((QUEUE) == (EM1FM2) ? (m_1) : (m_2));
	onPoint.x = profile->point->v.x;
	onPoint.y = profile->point->v.y;
	onPoint.z = profile->point->v.z;
	inMesh = ((QUEUE) == (EM1FM2) ? (m_2) : (m_1));
	inEdge = 0;
	inFace = iTmp->point->indexFace;

	// inizializzo prevFace e tanFace, di modo da poter iniziare anche da un punto di tangenza
	prevFace = 0;
	if(iTmp->point->tan==1){
		// conto i vertici tangenti nella mesh
		if(onMesh==m_1)
			tanCount = nTan1;
		else
			tanCount = nTan2;
		printf("tanCount %d\n",tanCount);
		tanFace = true;		
		i = onMesh->mod_find_in_vert(iTmp->point->v);
		// ho l'indice del punto,conosco quindi le facce a cui appartiene
		// determino la faccia tangente in cui mi trovo,se il punto ha più facce tangenti c'è ambiguità (si risolve collassando le facce tangenti)
		for(int u=0;u<onMesh->vert[i].val;u++){
			g = abs(onMesh->vert[i].edge[u]);
			if(onMesh->face[onMesh->edge[g].neigh[0]].tan==1){
				tanFaceIndex = onMesh->edge[g].neigh[0];						
				break;
			}
			else if(onMesh->face[onMesh->edge[g].neigh[1]].tan==1){
				tanFaceIndex = onMesh->edge[g].neigh[1];
				break;
			}
		}				
		qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
		while(qTmp1){
			if(qTmp1->tan!=1){
				// verifico se appartiene a una delle facce non tangenti a cui appartiene il punto tangente di partenza
				for(int v=0;v<mesh->vert[i].val;v++){
					if(mesh->face[mesh->vert[i].neigh[v]].tan==0){
						if(gen_pnpoly(mesh,mesh->vert[i].neigh[v],qTmp1->v)){
							prevFace = mesh->vert[i].neigh[v];
							break;
						}
					}
					if(prevFace!=0) break;
				}				
			}			
			else if(qTmp1->tan==1){
				tmp = 0;
				g = onMesh->mod_find_in_vert(qTmp1->v);
				// il punto con cui ho iniziato il profilo è il primo o l'ultimo nella sequenza dei punti della faccia, per costruzione
				// non deve essere un punto della mesh originale
				c = onMesh->mod_find_in_face(onMesh->face,tanFaceIndex,i);
				if(i!=g && (g>(onMesh->nVert)-tanCount) && (c==0 || c==onMesh->face[tanFaceIndex].nVert-1)){
					m = onMesh->mod_find_in_face(onMesh->face,tanFaceIndex,g);
					if((c==0 && m==1)||(c==onMesh->face[tanFaceIndex].nVert-1 && m==c-1)){
						for(int v=0;v<mesh->vert[i].val;v++){
							if(mesh->face[mesh->vert[i].face[v]].tan==0){
								for(int b=0;b<mesh->vert[g].val;b++){
									if(mesh->face[mesh->vert[g].face[b]].tan==0){
										if(mesh->vert[i].face[v]==mesh->vert[g].face[b]){
											printf("1- Per prevFace ho valutato il punto %g %g %g\n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
											printf("i %d g %d c %d m %d\n",i,g,c,m);
											tmp = mesh->vert[g].face[b]; // onFace
											break;
										}
									}
								}
							}
							if(tmp!=0) break;
						}
						for(int v=0;v<mesh->vert[i].val;v++){
							if(mesh->face[mesh->vert[i].face[v]].tan==0 && mesh->vert[i].face[v]!=tmp){
								prevFace = mesh->vert[i].face[v];
								break;
							}
						}
					}
				}
			}
			if(prevFace!=0) break;
			qTmp1 = qTmp1->next;
		}
		// se non ho determinato prevFace guardando i punti di tanFaceIndex e i punti non tangenti,la cerco guardando tutti i punti tangenti
		if(prevFace==0){
			qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
			while(qTmp1){
				g = onMesh->mod_find_in_vert(qTmp1->v);
				// devo prendere la faccia che non è tangente e a cui appartiene un altro punto di tangenza che non appartiene alla stessa faccia tangente
				if(i!=g && !(onMesh->mod_find_in_face(onMesh->face,tanFaceIndex,g)<onMesh->face[tanFaceIndex].nVert)){
					for(int v=0;v<mesh->vert[i].val;v++){
						if(mesh->face[mesh->vert[i].face[v]].tan==0){
							for(int b=0;b<mesh->vert[g].val;b++){
								if(mesh->face[mesh->vert[g].face[b]].tan==0){
									if(mesh->vert[i].face[v]==mesh->vert[g].face[b]){
										printf("2- Per prevFace ho valutato il punto %g %g %g\n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
										prevFace = mesh->vert[g].face[b];
										break;
									}
								}
							}
						}
						if(prevFace!=0) break;
					}
				}
				if(prevFace!=0) break;
				qTmp1 = qTmp1->next;
			}
		}
	}
	
	prevTanFaceIndex = -1;

	do {
		/* Si controlla se sono in un vertice in tangenza e devo gestire la faccia tangente. */
		if(iTmp->point->tan == 1 && tanFace==true){
			/* L'ultimo punto del profilo che ho inserito è un punto di tangenza.
			 * Devo aggiungere i vertici della faccia in tangenza fino ad arrivare a un vertice
			 * in tangenza su un altro edge della faccia. */			
			// determino in che faccia non tangente mi trovo, uso l'onFace del penultimo punto inserito nel profilo
			g = onMesh->mod_find_in_vert(iTmp->point->v);
			for(int vl=0;vl<onMesh->vert[g].val;vl++){
				if(onMesh->vert[g].face[vl]!=prevFace && onMesh->face[onMesh->vert[g].face[vl]].tan==0){
					onFace = onMesh->vert[g].face[vl];
					break;
				}
			}			
			// recupero l'indice nella faccia dell'ultimo punto inserito nel profilo
			i = onMesh->mod_find_in_face(onMesh->face,onFace,g);
			//for(i=0;i<onMesh->face[onFace].nVert;i++){
			//	if(onMesh->vert[onMesh->face[onFace].vert[i]].x==iTmp->point->v.x && onMesh->vert[onMesh->face[onFace].vert[i]].y==iTmp->point->v.y && onMesh->vert[onMesh->face[onFace].vert[i]].z==iTmp->point->v.z){
			//		break;
			//	}
			//}			
			// determino la faccia tangente in cui mi trovo
			for(int u=0;u<onMesh->vert[onMesh->face[onFace].vert[i]].val;u++){
				g = abs(onMesh->vert[onMesh->face[onFace].vert[i]].edge[u]);
				if(onMesh->face[onMesh->edge[g].neigh[0]].tan==1 && onMesh->edge[g].neigh[0]!=prevTanFaceIndex){
					tanFaceIndex = onMesh->edge[g].neigh[0];
					break;
				}
				else if(onMesh->face[onMesh->edge[g].neigh[1]].tan==1 && onMesh->edge[g].neigh[1]!=prevTanFaceIndex){
					tanFaceIndex = onMesh->edge[g].neigh[1];
					break;
				}
			}
			
			printf("tanFace: %d\n",tanFaceIndex);
			printf("prevTanFace: %d\n",prevTanFaceIndex);
			printf("prevFace: %d\n",prevFace);
			printf("onFace: %d\n",onFace);

			// scorro la faccia e aggiungo al profilo i punti in tangenza
			// (i punti in tangenza sono sempre il primo e gli ultimi nella sequenza
			// di punti della faccia,per costruzione)
			/* 
			 * Ad ogni punto che aggiungo devo controllare se vi è un altra faccia tangente adiacente
			 * su cui proseguire con la costruzione del profilo. Se si, interrompo l'aggiunta dei punti
			 * della faccia tangente corrente e continuo aggiungendo i punti della faccia tangente adiacente.
			 * Continuo dal punto, nell'altra faccia, consecutivo all'ultimo punto preso (cerca
			 * indice nella nuova faccia tangente dell'ultimo punto inserito) che ha in comune la stessa faccia non tangente.
			 */
			if(i==0){
				for(g=onMesh->face[onFace].nVert-1;g>0;g--){
					if(onMesh->vert[onMesh->face[onFace].vert[g]].tan==0) break;
					// recupero il punto nella lista dei punti di intersezione
					qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
					while(qTmp1){
						if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
							break;
						qTmp1 = qTmp1->next;
					}
					if(!qTmp1){
						// se il punto successivo è interno alla faccia originale,si trova nell'altra lista
						qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
								break;
							qTmp1 = qTmp1->next;
						}					
					}
					//Lo aggiungo al profilo
					iTmp->next = (i_point*) malloc(sizeof(i_point));
					if (!iTmp->next) ErrorMessage();
					iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
					iTmp->next->queueMesh = QUEUE;     /* su quale coda si trova */
					iTmp->next->next = NULL;
					iTmp->next->prev = iTmp;
					iTmp = iTmp->next;
					numTmp++;
					
					printf("Punto tangente, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
					// verifico a quante facce tangenti appartiene questo punto
					c = 0;
					m = onMesh->mod_find_in_vert(iTmp->point->v);
					for(int r=0;r<onMesh->vert[m].val;r++){
						if(onMesh->face[onMesh->vert[m].face[r]].tan!=0)
							c++;
					}
					if(c>1) break;
				}
				if(c>1){
					// devo proseguire lungo la nuova faccia tangente,cerco la faccia non tangente vicina
					// conto il numero di facce non tangenti vicine
					c = 0;
					for(int r=0;r<onMesh->vert[m].val;r++){
						if(onMesh->face[onMesh->vert[m].face[r]].tan==0)
							c++;
					}
					// se c'è una sola faccia non tangente non devo aggiornare nulla
					if(c==2){
						for(int r=0;r<onMesh->vert[m].val;r++){
							if(onMesh->face[onMesh->vert[m].face[r]].tan!=0 && onMesh->vert[m].face[r]!=onFace){
								// aggiorno onface e prevface,non occorre aggiornare onEdge perchè la prossima face da gestire è tangente e mi basta onFace
								prevFace = onFace;
								onFace = onMesh->vert[m].face[r];
								break;
							}
						}
					}
					// devo sottrarre il numero di punti della faccia in tangenza tanFaceIndex e rimuovere i punti dalle liste
					for(int r=0;r<onMesh->face[tanFaceIndex].nVert;r++){
						qTmp1 = *EM1_FM2;
						test1 = false;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM1_FM2, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						qTmp1 = *EM2_FM1;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM2_FM1, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						if(test1) nInt--;
					}						

					prevTanFaceIndex = tanFaceIndex;
					tanFace = true;
				}
				else if(c==1){
					g++;
					// sottraggo il numero di punti della faccia in tangenza
					for(int r=0;r<onMesh->face[tanFaceIndex].nVert;r++){
						qTmp1 = *EM1_FM2;
						test1 = false;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM1_FM2, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						qTmp1 = *EM2_FM1;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM2_FM1, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						if(test1) nInt--;
					}

					// aggiorno i parametri di lavoro
					// scelgo tra gli edge a cui appartiene il punto di tangenza quello che fa parte della faccia in cui mi trovo,
					// che fa parte di una faccia diversa da quella in cui mi trovo e diversa da quella in tangenza che ho inserito,
					// sarà l'edge di uscita
					for(int u=0;u<onMesh->vert[onMesh->face[onFace].vert[g]].val;u++){
						i = abs(onMesh->vert[onMesh->face[onFace].vert[g]].edge[u]);
						if(onMesh->edge[i].neigh[0]!=onFace &&
						   onMesh->edge[i].neigh[1]==onFace &&
						   onMesh->edge[i].neigh[0]!=tanFaceIndex){
							onEdge = i;
							break;
						}
						else if(onMesh->edge[i].neigh[1]!=onFace &&
								onMesh->edge[i].neigh[0]==onFace &&
								onMesh->edge[i].neigh[1]!=tanFaceIndex){
							onEdge = i;
							break;
						}
					}
					prevFace = onFace;
					if (onFace != onMesh->edge[onEdge].neigh[0])
						onFace = onMesh->edge[onEdge].neigh[0];
					else
						onFace = onMesh->edge[onEdge].neigh[1];

					tanFace = false;

					// Come determino inEdge e inFace?
					// Non posso,i punti di tangenza sono vertici a valenza maggiore di due.
					// Anche se escludessi la faccia in tangenza,dovrei scegliere inFace tra
					// almeno due facce senza avere a disposizione informazioni aggiuntive.
					// => le informazioni indexEdge indexFace dei punti in tangenza non sono affidabili
					/* Sono arrivato in una nuova faccia onFace. Parto da un vertice di tangenza:
					 * - se i punti interni a onFace sono 0,cerco un altro punto di intersezione
					 *   sugli edge di onFace
					 * - se ho un punto interno a onFace,devo passare sull'altra mesh.Il punto che cerco
					 *   avrà un valore di indexEdge e di indexFace corretto e quindi posso aggiungerlo
					 *   senza problemi.
					 * - Se la faccia ha più di un punto interno,cambio mesh. Le informazioni di indexEdge
					 *   e di indexFace sono corrette.
					 *   Per scegliere il primo tra tutti i punti che intersecano onFace,prendo quello che
					 *   sta su un edge della faccia in cui si trova l'edge con il vertice di tangenza.
					 *
					 *   In tutti i casi, il punto di uscita dà problemi solo se è un punto in tangenza,
					 *   nel qual caso dovrò cercarlo verificando tra i punti in tangenza quale appartiene
					 *   a un edge della faccia in cui mi trovo.
					 *   Devo quindi cercare tra i punti normalmente,escludendo quelli in tangenza e,se non
					 *   trovo un punto di uscita,esaminare quelli in tangenza.
					 *   Notare che quando trovo un punto in tangenza ci saranno almeno due punti in tangenza
					 *   sullo stesso edge: devo prendere quello che ha solo una coordinata differente dal
					 *   precedente,ovvero quello che raggiungo muovendomi lungo un edge.
					 *   Quando arrivo a un punto in tangenza, devo stabilire il valore di onFace.
					 */
				}
			}
			else if(i!=0){
				// devo decidere il verso in base agli ultimi due punti inseriti TODO
				// prendo l'indice in onFace del penultimo punto del profilo
				if(iTmp->prev!=NULL){
					g = onMesh->mod_find_in_vert(iTmp->prev->point->v);
					g = onMesh->mod_find_in_face(onMesh->face,onFace,g);
				}
				// se appartiene a onFace devo procedere come nel caso i=0,ma partendo da i-1
				if(iTmp->prev!=NULL && g<onMesh->face[onFace].nVert){
					for(g=i-1;g>0;g--){
						if(onMesh->vert[onMesh->face[onFace].vert[g]].tan==0) break;
						// recupero il punto nella lista dei punti di intersezione
						qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
								break;
							qTmp1 = qTmp1->next;
						}
						if(!qTmp1){
							// se il punto successivo è interno alla faccia originale,si trova nell'altra lista
							qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
							while(qTmp1){
								if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
									break;
								qTmp1 = qTmp1->next;
							}
						}
						//Lo aggiungo al profilo
						iTmp->next = (i_point*) malloc(sizeof(i_point));
						if (!iTmp->next) ErrorMessage();
						iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
						iTmp->next->queueMesh = QUEUE;     /* su quale coda si trova */
						iTmp->next->next = NULL;
						iTmp->next->prev = iTmp;
						iTmp = iTmp->next;
						numTmp++;
						
						printf("Punto tangente, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
						// verifico a quante facce tangenti appartiene questo punto
						c = 0;
						m = onMesh->mod_find_in_vert(iTmp->point->v);
						for(int r=0;r<onMesh->vert[m].val;r++){
							if(onMesh->face[onMesh->vert[m].face[r]].tan!=0)
								c++;
						}
						if(c>1) break;
						// se sono arrivato a un punto ins, ho finito la zona di tangenza
						if(iTmp->point->ins==1){
							printf("tangenza finita\n");
							// sottraggo il numero di punti della faccia in tangenza
							for(int r=0;r<onMesh->face[tanFaceIndex].nVert;r++){
								qTmp1 = *EM1_FM2;
								test1 = false;
								while(qTmp1){
									if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
										if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
											if(removePoint(qTmp1, EM1_FM2, &flag))
												test1 = true;
											break;
										}
									}
									qTmp1 = qTmp1->next;
								}
								qTmp1 = *EM2_FM1;
								while(qTmp1){
									if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
										if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
											if(removePoint(qTmp1, EM2_FM1, &flag))
												test1 = true;
											break;
										}
									}
									qTmp1 = qTmp1->next;
								}
								if(test1) nInt--;
							}

							// aggiorno i parametri di lavoro
							// scelgo tra gli edge a cui appartiene il punto di tangenza quello che fa parte di
							// una faccia diversa da quella in cui mi trovo e diversa da quella in tangenza che ho inserito,
							// sarà l'edge di uscita
							for(int u=0;u<onMesh->vert[onMesh->face[onFace].vert[g]].val;u++){
								i = abs(onMesh->vert[onMesh->face[onFace].vert[g]].edge[u]);
								if(onMesh->edge[i].neigh[0]!=onFace &&
										onMesh->edge[i].neigh[1]==onFace &&
										onMesh->edge[i].neigh[0]!=tanFaceIndex){
									onEdge = i;
									printf("scelto edge %d - %d\n",onMesh->edge[onEdge].vert[0],onMesh->edge[onEdge].vert[1]);
									break;
								}
								else if(onMesh->edge[i].neigh[1]!=onFace &&
										onMesh->edge[i].neigh[0]==onFace &&
										onMesh->edge[i].neigh[1]!=tanFaceIndex){
									onEdge = i;
									printf("scelto edge %d - %d\n",onMesh->edge[onEdge].vert[0],onMesh->edge[onEdge].vert[1]);
									break;
								}
							}
							prevFace = onFace;
							if (onFace != onMesh->edge[onEdge].neigh[0])
								onFace = onMesh->edge[onEdge].neigh[0];
							else
								onFace = onMesh->edge[onEdge].neigh[1];

							prevTanFaceIndex = tanFaceIndex;
							tanFace = false;
							break;
						}
					}
				}
				else{
					for(g=i+1;g<onMesh->face[onFace].nVert;g++){
						printf("i %d nVert %d\n",i,onMesh->face[onFace].nVert);
						// recupero il punto nella lista dei punti di intersezione
						qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
								break;
							qTmp1 = qTmp1->next;
						}
						if(!qTmp1){
							// se il punto successivo è interno alla faccia originale,si trova nell'altra lista
							qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
							while(qTmp1){
								if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
									break;
								qTmp1 = qTmp1->next;
							}
						}
						//Lo aggiungo al profilo
						iTmp->next = (i_point*) malloc(sizeof(i_point));
						if (!iTmp->next) ErrorMessage();
						iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
						iTmp->next->queueMesh = QUEUE;     /* su quale coda si trova */
						iTmp->next->next = NULL;
						iTmp->next->prev = iTmp;
						iTmp = iTmp->next;
						numTmp++;
						
						printf("Punto tangente, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
						// verifico a quante facce tangenti appartiene questo punto
						c = 0;
						m = onMesh->mod_find_in_vert(iTmp->point->v);
						for(int r=0;r<onMesh->vert[m].val;r++){
							if(onMesh->face[onMesh->vert[m].face[r]].tan!=0)
								c++;
						}
						if(c>1) break;
					}
				}
				if(c>1){
					// devo proseguire lungo la nuova faccia tangente,cerco la faccia non tangente vicina
					// conto il numero di facce non tangenti vicine
					c = 0;
					for(int r=0;r<onMesh->vert[m].val;r++){
						if(onMesh->face[onMesh->vert[m].face[r]].tan==0)
							c++;
					}
					// se c'è una sola faccia non tangente non devo aggiornare nulla
					if(c==2){
						for(int r=0;r<onMesh->vert[m].val;r++){
							if(onMesh->face[onMesh->vert[m].face[r]].tan!=0 && onMesh->vert[m].face[r]!=onFace){
								// aggiorno onface e prevface,non occorre aggiornare onEdge perchè la prossima face da gestire è tangente e mi basta onFace
								prevFace = onFace;
								onFace = onMesh->vert[m].face[r];
								break;
							}
						}
					}
					// devo sottrarre il numero di punti della faccia in tangenza tanFaceIndex
					for(int r=0;r<onMesh->face[tanFaceIndex].nVert;r++){
						qTmp1 = *EM1_FM2;
						test1 = false;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM1_FM2, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						qTmp1 = *EM2_FM1;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM2_FM1, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						if(test1) nInt--;
					}						

					prevTanFaceIndex = tanFaceIndex;
					tanFace = true;
				}
				else if(c==1 && tanFace==true){
					// inserisco il punto g=0;
					g=0;
					// recupero il punto nella lista dei punti di intersezione
					qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
					while(qTmp1){
						if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
							break;
						qTmp1 = qTmp1->next;
					}
					if(!qTmp1){
						qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[onFace].vert[g]].x && qTmp1->v.y==onMesh->vert[onMesh->face[onFace].vert[g]].y && qTmp1->v.z==onMesh->vert[onMesh->face[onFace].vert[g]].z)
								break;
							qTmp1 = qTmp1->next;
						}
					}
					//Lo aggiungo al profilo
					iTmp->next = (i_point*) malloc(sizeof(i_point));
					if (!iTmp->next) ErrorMessage();
					iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
					iTmp->next->queueMesh = QUEUE;     /* su quale coda si trova */
					iTmp->next->next = NULL;
					iTmp->next->prev = iTmp;
					iTmp = iTmp->next;
					numTmp++;
					/* Rimuovo i punti della faccia in tangenza dalle liste e ne sottraggo il numero */
					printf("Punto tangente, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);										
					for(int r=0;r<onMesh->face[tanFaceIndex].nVert;r++){
						qTmp1 = *EM1_FM2;
						test1 = false;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM1_FM2, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						qTmp1 = *EM2_FM1;
						while(qTmp1){
							if(qTmp1->v.x==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].x && qTmp1->v.y==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].y && qTmp1->v.z==onMesh->vert[onMesh->face[tanFaceIndex].vert[r]].z){
								if(qTmp1->v.x!=profile->point->v.x || qTmp1->v.y!=profile->point->v.y || qTmp1->v.z!=profile->point->v.z){
									if(removePoint(qTmp1, EM2_FM1, &flag))
										test1 = true;
									break;
								}
							}
							qTmp1 = qTmp1->next;
						}
						if(test1) nInt--;
					}

					// aggiorno i parametri di lavoro
					// scelgo tra gli edge a cui appartiene il punto di tangenza quello che fa parte di
					// una faccia diversa da quella in cui mi trovo e diversa da quella in tangenza che ho inserito,
					// sarà l'edge di uscita
					for(int u=0;u<onMesh->vert[onMesh->face[onFace].vert[g]].val;u++){
						i = abs(onMesh->vert[onMesh->face[onFace].vert[g]].edge[u]);
						if(onMesh->edge[i].neigh[0]!=onFace &&
						   onMesh->edge[i].neigh[1]==onFace &&
						   onMesh->edge[i].neigh[0]!=tanFaceIndex){
							onEdge = i;
							printf("scelto edge %d - %d\n",onMesh->edge[onEdge].vert[0],onMesh->edge[onEdge].vert[1]);
							break;
						}
						else if(onMesh->edge[i].neigh[1]!=onFace &&
								onMesh->edge[i].neigh[0]==onFace &&
								onMesh->edge[i].neigh[1]!=tanFaceIndex){
							onEdge = i;
							printf("scelto edge %d - %d\n",onMesh->edge[onEdge].vert[0],onMesh->edge[onEdge].vert[1]);
							break;
						}
					}
					prevFace = onFace;
					if (onFace != onMesh->edge[onEdge].neigh[0])
						onFace = onMesh->edge[onEdge].neigh[0];
					else
						onFace = onMesh->edge[onEdge].neigh[1];

					tanFace = false;
				}
			}
			onPoint.x = iTmp->point->v.x;
			onPoint.y = iTmp->point->v.y;
			onPoint.z = iTmp->point->v.z;
			inFace = 0;		// per indicare che è cambiata la faccia intersecata
		}

		if(tanFace) continue;

		printf("onFace %d\n",onFace);
		printf("prevFace %d\n",prevFace);

		/* si controlla se la scelta da fare è ambigua:
	       -la face in cui si intende proseguire contiene più punti;
	       -il punto di intersezione su cui ci si trova è su un vertice.
	       -se il punto su cui ci si trova è di tangenza,la scelta è sicura.
	    */

		test1 = false;
		if (onMesh->face[onFace].pointInto > 1) test1 = true;
		for (i=0; i < onMesh->face[onFace].nVert; i++) {
			if ( iTmp->point->tan == 0 &&
				((float)onMesh->vert[onMesh->face[onFace].vert[i]].x == (float)iTmp->point->v.x) &&
				((float)onMesh->vert[onMesh->face[onFace].vert[i]].y == (float)iTmp->point->v.y) &&
				((float)onMesh->vert[onMesh->face[onFace].vert[i]].z == (float)iTmp->point->v.z) )
			{ test1 = true;  break; }
		}

		if (!test1) { /* se la scelta è sicura, si può cercare il prossimo punto
	                     da inserire, se la face aveva un punto interno sarà
	                     possibile effettuare un doppio inserimento:
	                     il punto interno e il punto di uscita dalla face. */

			/*
	         MORENO: Devo trattare il caso dell'ambiguità per il vertice di uscita e il punto interno
	         -Punti interni alla face = 0 -> controllo che le coppie entrata-uscita appartengano
	          alla stessa face nell'altra mesh
	         -Punti interni alla face = 1 -> controllo che l'indexEdge del punto interno alla
	          face faccia parte della face intersecata dal punto di ingresso (indexFace)
			 */
			test2=false;
			if (onMesh->face[onFace].pointInto == 0) test2 = true;
			if (onMesh->face[onFace].pointInto == 1) {

				qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));

				do { /* si esclude un eventuale punto generato
	                dall'intersezione di due edge */
					if ( (qTmp1->indexFace == onFace) &&
							(((float)qTmp1->v.x != (float)iTmp->point->v.x) ||
							((float)qTmp1->v.y != (float)iTmp->point->v.y) ||
							((float)qTmp1->v.z != (float)iTmp->point->v.z)) &&
							!gen_checkIntersection(onMesh, qTmp1->v, onFace, NULL,
							((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1)), NULL) ) break;
					qTmp1 = qTmp1->next;
				} while (qTmp1);				
				
				/*controllo che l'indexEdge del punto interno alla face faccia parte della
	        	face intersecata dal punto di ingresso (indexFace) */
				test1=false;
				tmpMesh=(iTmp->queueMesh==EM1FM2)?m_2:m_1;
				for(i=0; i < tmpMesh->face[iTmp->point->indexFace].nVert ;i++){
					if(tmpMesh->face[iTmp->point->indexFace].edge[i]==qTmp1->indexEdge){
						test1=true;
						break;
					}
				}
				//MORENO: se il punto qTmp1 è il primo inserito nel profilo, ho finito
				if(test1==true && qTmp1!=NULL && (float)profile->point->v.x==(float)qTmp1->v.x && (float)profile->point->v.y==(float)qTmp1->v.y && (float)profile->point->v.z==(float)qTmp1->v.z){
					ret = 1;
					break;
				}

				if (test1==true && qTmp1) { /* fb: AGGIUNTA DA VERIFICARE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
					iTmp->next = (i_point*) malloc(sizeof(i_point));
					if (!iTmp->next) ErrorMessage();
					iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
					iTmp->next->queueMesh = !QUEUE;    /* su quale coda si trova */
					iTmp->next->next = NULL;
					iTmp->next->prev = iTmp;
					iTmp = iTmp->next;
					nInt -= 1;
					numTmp++;
					/*
	        MORENO
	        Rimuovo il punto inserito dalla lista
					 */
					//printf("\nScelta sicura, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
					//printf("\nLista da cui rimuovo: %d \n",(!QUEUE==EM1FM2)?1:2);
					removePoint(qTmp1, EM1_FM2, &flag);
					removePoint(qTmp1, EM2_FM1, &flag);

				}

				/*                  ATTENZIONE ! ! ! !
	           FB: questa è il modo giusto per detrminare la nuva face in cui
	               si va ad intersecare, ma non è affidabile nel caso di punti
	               di intersezione coincidenti a vertici!!! */
				/*
	        if (inFace != inMesh->edge[iTmp->point->indexEdge].neigh[0])
	          inFace = inMesh->edge[iTmp->point->indexEdge].neigh[0];
	        else
	          inFace = inMesh->edge[iTmp->point->indexEdge].neigh[1];
				 */

				inFace = 0;  /* un punto interno indica che si è
	                        passati ad intersecare un'altra face */

			}

			/* il punto di uscita dalla face è comunque da inserire, nel caso non
	         sia il primo punto da cui è stata costruita la poligonale  */
			/* Il punto di uscita dà problemi solo se è un punto in tangenza,
			 * nel qual caso dovrò cercarlo verificando tra i punti in tangenza quale appartiene
			 * a un edge della faccia in cui mi trovo.
			 * Devo quindi cercare tra i punti normalmente,escludendo quelli in tangenza e,se non
			 * trovo un punto di uscita,esaminare quelli in tangenza.
			 * Notare che quando trovo un punto in tangenza ci saranno almeno due punti in tangenza
			 * sullo stesso edge: devo prendere quello che ha solo una coordinata differente dal
			 * precedente,ovvero quello che raggiungo muovendomi lungo un segmento.
			 * Quando arrivo a un punto in tangenza, devo stabilire il valore di onFace. */

			for (i=0; i < onMesh->face[onFace].nVert; i++) {

				test1 = false;
				qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
				while(qTmp1) {
					// non considero i punti in tangenza
					if(qTmp1->tan==1){ qTmp1=qTmp1->next; continue; }
					// printf("punto %g %g %g\n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
					if ( (onMesh->face[onFace].edge[i] == qTmp1->indexEdge) &&
							(inFace == 0 || inFace == qTmp1->indexFace) &&
							(((float)onPoint.x != (float)qTmp1->v.x) ||
							((float)onPoint.y != (float)qTmp1->v.y) ||
							((float)onPoint.z != (float)qTmp1->v.z)) ) {
						/* se non c'erano punti interni, controllo che le coppie entrata-uscita
	                   appartengano alla stessa face nell'altra mesh */
						if(test2){
							if(qTmp1->indexFace == iTmp->point->indexFace){
								test1 = true;
								break;
							}
						}
						/* se c'era un punto interno,controllo che l'indexEdge dell'ultimo
	                      punto inserito nel profilo appartenga alla face che viene intersecata
	                      dal punto di uscita */
						else{
							tmpMesh=(iTmp->queueMesh==EM1FM2)?m_1:m_2;
							for(i=0; i < tmpMesh->face[qTmp1->indexFace].nVert; i++){
								if(iTmp->point->indexEdge == tmpMesh->face[qTmp1->indexFace].edge[i]){
									test1 = true;
									break;
								}
							}
							if(test1) break;
						}
					}
					qTmp1 = qTmp1->next;
				}

				if (test1) break;
			}
			// Se non ho trovato un punto, cerco tra quelli in tangenza
			if(!test1){
				qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
				printf("cerco tra i punti in tangenza nella faccia %d: ",onFace);
				while(qTmp1) {
					printf("onPoint %g %g %g\n",onPoint.x,onPoint.y,onPoint.z);
					printf("valuto %g %g %g tan %d ins %d\n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z,qTmp1->tan,qTmp1->ins);
					if(qTmp1->tan==0){ qTmp1=qTmp1->next; continue; }
					// verifico se il punto è un vertice della faccia in cui mi trovo,
					// se è diverso dall'ultimo punto inserito e
					// se non era un vertice prima della creazione delle facce di tangenza
					for(h=0;h<onMesh->face[onFace].nVert;h++){
						p0.x = onMesh->vert[onMesh->face[onFace].vert[h]].x;
						p0.y = onMesh->vert[onMesh->face[onFace].vert[h]].y;
						p0.z = onMesh->vert[onMesh->face[onFace].vert[h]].z;
						if ((((float)onPoint.x != (float)qTmp1->v.x)||((float)onPoint.y != (float)qTmp1->v.y)||((float)onPoint.z != (float)qTmp1->v.z)) &&
							 ((float)p0.x == (float)qTmp1->v.x)&&((float)p0.y == (float)qTmp1->v.y)&&((float)p0.z == (float)qTmp1->v.z)){

							// controllo se il vertice,escludendo le facce in tangenza,ha valenza due
							//tmp = 0;
							//n = onMesh->mod_find_in_vert(qTmp1->v);
							//for(int u=0;u<onMesh->vert[n].val;u++){
							//	if(onMesh->face[onMesh->vert[n].neigh[u]].tan == 0)
							//		tmp++;
							//}if(tmp==2){
							if(qTmp1->ins==1){
								// ho trovato il punto
								test1 = true;
								break;
							}
						}
					}
					if(test1) break;
					qTmp1 = qTmp1->next;
				}
			}
			test1 = false;
			
			if(!qTmp1){
				printf("non ho trovato un punto per continuare la costruzione del profilo --> zona di tangenza isolata\n");
				*np = 1;
				// devo rimuovere il primo punto del profilo dalle liste
				removePoint(profile->point, EM1_FM2, &flag);
				removePoint(profile->point, EM2_FM1, &flag);
				*count = nInt;
				*num = numTmp;
				return NULL;
			}
			//MORENO: se il punto qTmp1 è il primo inserito nel profilo, ho finito
			if((float)profile->point->v.x==(float)qTmp1->v.x && (float)profile->point->v.y==(float)qTmp1->v.y && (float)profile->point->v.z==(float)qTmp1->v.z){
				ret = 1;
			}
			else{
				iTmp->next = (i_point*) malloc(sizeof(i_point));
				if (!iTmp->next) ErrorMessage();
				iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
				iTmp->next->queueMesh = QUEUE;     /* su quale coda si trova */
				iTmp->next->next = NULL;
				iTmp->next->prev = iTmp;
				iTmp = iTmp->next;
				nInt -= 1;
				numTmp++;
				/*
	            MORENO
	            Rimuovo il punto inserito dalla lista
				 */
				printf("Scelta sicura 2, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
				//printf("\nLista da cui rimuovo: %d \n",(QUEUE==EM1FM2)?1:2);
				removePoint(qTmp1, EM1_FM2, &flag);
				removePoint(qTmp1, EM2_FM1, &flag);
				/*
	            Se la lista da cui ho rimosso il punto adesso è vuota,cambio coda
	            Cerco un punto nell'altra lista che è all'interno della faccia su
	            cui dovrei muovermi.
				 */
				if((QUEUE==EM1FM2 && *EM1_FM2==NULL) || (QUEUE==EM2FM1 && *EM2_FM1==NULL)){
					onPoint.x = iTmp->point->v.x;
					onPoint.y = iTmp->point->v.y;
					onPoint.z = iTmp->point->v.z;
					QUEUE = (QUEUE==EM1FM2)?EM2FM1:EM1FM2;
					qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
					prevFace = onFace;
					onFace = iTmp->point->indexFace; /* face dell'ultimo punto */
					onMesh = ((QUEUE) == (EM1FM2) ? (m_1) : (m_2));
					inMesh = ((QUEUE) == (EM1FM2) ? (m_2) : (m_1));
					// recupero dal profilo il punto che sta sull'altro edge della faccia
					riTmp = profile;
					while(riTmp!=NULL && riTmp->queueMesh==QUEUE && riTmp->point->indexFace!=onFace){
						riTmp=riTmp->next;
					}

					for(i=0; i < onMesh->face[onFace].nVert; i++){
						while(qTmp1){
							// salto i punti in tangenza
							if(qTmp1->tan==1){ qTmp1=qTmp1->next; continue; }
							if((onMesh->face[onFace].edge[i] == qTmp1->indexEdge) &&
								(((float)riTmp->point->v.x != (float)qTmp1->v.x) ||
								((float)riTmp->point->v.y != (float)qTmp1->v.y) ||
								((float)riTmp->point->v.z != (float)qTmp1->v.z))) {

								test1=true; break;
							}
							qTmp1=qTmp1->next;
						}
						if(test1) break;
						qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM1_FM2) : (*EM2_FM1));
					}

					// Se è il primo punto del profilo ho finito
					if(profile->point==qTmp1){
						ret = 1;
					}
					else{
						//Lo aggiungo al profilo, aggiorno i parametri di lavoro e continuo
						iTmp->next = (i_point*) malloc(sizeof(i_point));
						if (!iTmp->next) ErrorMessage();
						iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
						iTmp->next->queueMesh = QUEUE;     /* su quale coda si trova */
						iTmp->next->next = NULL;
						iTmp->next->prev = iTmp;
						iTmp = iTmp->next;
						nInt -= 1;
						numTmp++;
						/* Rimuovo il punto inserito dalla lista */
						//printf("\nScelta sicura 3, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
						//printf("\nLista da cui rimuovo: %d \n",(QUEUE==EM1FM2)?1:2);
						removePoint(qTmp1, EM1_FM2, &flag);
						removePoint(qTmp1, EM2_FM1, &flag);

						onEdge = iTmp->point->indexEdge;  /* ci si sposta sull'edge di uscita */
						prevFace = onFace;
						if (onFace != onMesh->edge[onEdge].neigh[0])
							onFace = onMesh->edge[onEdge].neigh[0];
						else
							onFace = onMesh->edge[onEdge].neigh[1];

						inEdge = 99;  /* tale valore indica una storia del profilo */
						inFace = iTmp->point->indexFace;  /* in particolare quale face si sta intersecando */
					}
				}
				else{
					/* Prima di ripartire si aggiornano le condizioni di ricerca.
	                QUEUE e onMesh rimangono tali, la ricerca per ora, continua
	                dalla stessa coda. */
					onPoint.x = iTmp->point->v.x;
					onPoint.y = iTmp->point->v.y;
					onPoint.z = iTmp->point->v.z;
					onEdge = iTmp->point->indexEdge;  /* ci si sposta sull'edge di uscita */
					prevFace = onFace;
					if (onFace != onMesh->edge[onEdge].neigh[0])
						onFace = onMesh->edge[onEdge].neigh[0];
					else
						onFace = onMesh->edge[onEdge].neigh[1];

					inEdge = 99;  /* tale valore indica una storia del profilo */
					inFace = iTmp->point->indexFace;  /* in particolare quale face si sta intersecando */
				}
			}
			if(iTmp->point->tan==1) tanFace = true;
		} else { /* Scelta ambigua */

			/* Per rendere sicura la scelta bisogna spostarsi sull'altra coda,
	         in particolare scegliere in maniera coerente il punto interno alla
	         face e poi aggiornare le condizioni di ricerca, essendosi posizionati
	         su un edge dell'altra mesh. */
			/*  Se l'ultimo punto del profilo è un punto di tangenza,per scegliere il primo
			*   tra tutti i punti che intersecano onFace,prendo quello che
			*   sta su un edge della faccia in cui si trova l'edge con il vertice di tangenza. */
			if(iTmp->point->tan==1 && tanFace==false){
				/* Controllo i punti dell'altra mesh che intersecano la faccia onFace.
				 * Dall'indexEdge di questi punti risalgo alla faccia a cui appartiene anche il vertice di tangenza inserito.
				 * Scelgo il punto che sta su un edge della stessa faccia a cui appartiene il vertice di tangenza.
				 * Quindi per ciascun edge trovato verifico le due facce neigh[]:
				 * controllo se il punto di tangenza appartiene a uno degli edge di queste facce. */
				test1 = false;
				qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
				do{
					if(qTmp1->tan==1){ qTmp1=qTmp1->next; continue; }
					if(qTmp1->indexFace==onFace){
						for(int h=0;h<inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[0]].nVert;h++){
							if(iTmp->point->v.x== inMesh->vert[inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[0]].vert[h]].x &&
							   iTmp->point->v.y== inMesh->vert[inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[0]].vert[h]].y &&
							   iTmp->point->v.z== inMesh->vert[inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[0]].vert[h]].z ){

								iTmp->point->indexFace = inMesh->edge[qTmp1->indexEdge].neigh[0];
								test1 = true;
								break;
							}
						}
						if(!test1){
							for(int h=0;h<inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[1]].nVert;h++){
								if(iTmp->point->v.x== inMesh->vert[inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[1]].vert[h]].x &&
								   iTmp->point->v.y== inMesh->vert[inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[1]].vert[h]].y &&
								   iTmp->point->v.z== inMesh->vert[inMesh->face[inMesh->edge[qTmp1->indexEdge].neigh[1]].vert[h]].z ){

									iTmp->point->indexFace = inMesh->edge[qTmp1->indexEdge].neigh[1];
									test1 = true;
									break;
								}
							}
						}
					}
					if(test1) break;
					qTmp1 = qTmp1->next;
				}while (qTmp1);
				inFace = iTmp->point->indexFace; /* face dell'ultimo punto */
				/* qTmp1 punta al nuovo elemento da inserire */
				inEdge = qTmp1->indexEdge;
			}
			else{
				v.x = iTmp->point->v.x;
				v.y = iTmp->point->v.y;
				v.z = iTmp->point->v.z;
				qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
				test1 = false;
				inFace = iTmp->point->indexFace; /* face dell'ultimo punto */

				if (!inEdge) { /* inizialmente ... */

					for (i=0; i < inMesh->face[inFace].nVert; i++) {
						/* ... si cerca un edge della face intersecata, in particolare
	             non deve essere un punto di intersezione edge-edge */

						do {
							if ((inMesh->face[inFace].edge[i] == qTmp1->indexEdge) &&
									(((float)v.x != (float)qTmp1->v.x) ||
											((float)v.y != (float)qTmp1->v.y) ||
											((float)v.z != (float)qTmp1->v.z)) ) { test1 = true; break; }
							qTmp1 = qTmp1->next;
						} while (qTmp1);

						if (test1) break;
						else qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));


					}
					/* qTmp1 punta al nuovo elemento da inserire */
					inEdge = qTmp1->indexEdge;


				} else {
					/* se si possiede una parte del profilo precedente ci sono due casi:
	           -ci si trova su un punto edge-edge;
	           -si risale all'ultimo punto dell'altra mesh inserito. */
					for (i=0; i < inMesh->face[inFace].nVert; i++) {
						do {
							if(qTmp1->tan==1) continue;
							if ((inMesh->face[inFace].edge[i] == qTmp1->indexEdge) &&
									((float)v.x == (float)qTmp1->v.x) &&
									((float)v.y == (float)qTmp1->v.y) &&
									((float)v.z == (float)qTmp1->v.z)) { test1 = true; break; }
							qTmp1 = qTmp1->next;
						} while (qTmp1);

						if (test1) break;
						else qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
					}

					if (test1) { /* punto edge-edge */
						inEdge = qTmp1->indexEdge;  /* da non considerare */
					} else {
						/* si risale profilo */
						riTmp = iTmp;
						do {
							if (riTmp->queueMesh == !QUEUE) break;
							riTmp = riTmp->prev;
						} while (riTmp);
						inEdge = riTmp->point->indexEdge;  /* da non considerare */
					}

					/* sapendo quale edge della face inFace è da escludere, si cerca
	           il punto successivo dato da un altro edge della stessa face */
					test1 = false;
					for (i=0; i < inMesh->face[inFace].nVert; i++) {

						qTmp1 = ((QUEUE) == (EM1FM2) ? (*EM2_FM1) : (*EM1_FM2));
						do {
							if ( (inMesh->face[inFace].edge[i] != inEdge) &&
									(inMesh->face[inFace].edge[i] == qTmp1->indexEdge) )
							{ test1 = true; break; }
							qTmp1 = qTmp1->next;
						} while (qTmp1);
						if (test1) break;
					}
				}
			}
			if(!qTmp1){
				printf("non ho trovato un punto per continuare la costruzione del profilo --> zona tangente isolata\n");
				*np = 1;
				// rimuovo il primo punto del profilo dalle liste
				// devo rimuovere il primo punto del profilo dalle liste
				removePoint(profile->point, EM1_FM2, &flag);
				removePoint(profile->point, EM2_FM1, &flag);
				*count = nInt;
				*num = numTmp;
				return NULL;
			}
			//MORENO: se il punto è il primo messo nel profilo, ho finito
			if(profile->point==qTmp1){
				ret = 1;
			}
			else{
				iTmp->next = (i_point*) malloc(sizeof(i_point));
				if (!iTmp->next) ErrorMessage();
				iTmp->next->point = qTmp1;         /* puntatore al punto inserito */
				iTmp->next->queueMesh = !QUEUE;    /* su quale coda si trova */
				iTmp->next->next = NULL;
				iTmp->next->prev = iTmp;
				iTmp = iTmp->next;
				nInt -= 1;
				numTmp++;
				/*
	        MORENO
	        Rimuovo il punto inserito dalla lista
				 */
				//printf("\n\nScelta ambigua, aggiunto punto al profilo:  %g %g %g \n",qTmp1->v.x,qTmp1->v.y,qTmp1->v.z);
				//printf("\nLista da cui rimuovo: %d \n",(!QUEUE==EM1FM2)?1:2);
				removePoint(qTmp1, EM1_FM2, &flag);
				removePoint(qTmp1, EM2_FM1, &flag);


				onPoint.x = iTmp->point->v.x;
				onPoint.y = iTmp->point->v.y;
				onPoint.z = iTmp->point->v.z;
				QUEUE = !QUEUE;
				onMesh = ((QUEUE) == (EM1FM2) ? (m_1) : (m_2));
				onEdge = iTmp->point->indexEdge;
				prevFace = onFace;
				if ( onMesh->edge[onEdge].neigh[0] != inFace) {
					inFace = iTmp->point->indexFace;
					onFace = onMesh->edge[onEdge].neigh[0];
				} else {
					inFace = iTmp->point->indexFace;
					onFace = onMesh->edge[onEdge].neigh[1];
				}
				inMesh = ((QUEUE) == (EM1FM2) ? (m_2) : (m_1));
			}
			if(iTmp->point->tan==1) tanFace = true;
		}
	} while (ret == 0);

	/* Devo rimuovere il primo punto del profilo dalla lista delle intersezioni */
	//printf("\nRimozione punto iniziale\n");
	//printf("Lista da cui rimuovo: %d\n",(profile->queueMesh == EM1FM2)?1:2);
	removePoint(profile->point, EM1_FM2, &flag);
	removePoint(profile->point, EM2_FM1, &flag);

	/*
	  Se tutti i punti del profilo stanno all'interno di una stessa faccia della stessa mesh, devo
	  segnarmi la faccia nella lista di facce da suddividere
	 */
	bool buildPolyAbort = true;
	int fc = profile->point->indexFace;
	char qm = profile->queueMesh;
	iTmp = profile;
	iTmp = iTmp->next;
	while(iTmp){
		/* (La queueMesh non dovrebbe cambiare mai) */
		if(qm==iTmp->queueMesh && fc!=iTmp->point->indexFace){
			buildPolyAbort = false;
			break;
		}
		iTmp = iTmp->next;

	}

	if(buildPolyAbort == true){
		//segno la faccia da triangolarizzare
		for(h=0;h<MAXVAL;h++){
			if(faceSplit->at(h)==-1)
				break;
		}
		faceSplit->at(h)=fc;
		//segno la mesh a cui appartiene la faccia
		queueM->at(h)=(profile->queueMesh==EM1FM2)?EM1FM2:EM2FM1;
		//inserisco i punti del profilo nelle liste delle intersezioni (in coda)
		if(profile->queueMesh == EM1FM2)
			qTmp1 = *EM1_FM2;
		else
			qTmp1 = *EM2_FM1;

		if(qTmp1!=NULL){
			while(qTmp1->next)
				qTmp1 = qTmp1->next;
		}

		iTmp = profile;
		while(iTmp){
			if(!qTmp1)
				qTmp1 = iTmp->point;
			else{
				qTmp1->next = iTmp->point;
				qTmp1 = qTmp1->next;
			}
			iTmp = iTmp->next;
		}
		qTmp1->next = NULL;
	}

#if DEBUG_GLUE
	iTmp = profile;
	printf("POLY-PROFILE:\n");
	do {
		printf("  x: %g  y: %g  z: %g tan: %d ins: %d\n",profile->point->v.x,profile->point->v.y,profile->point->v.z,profile->point->tan,profile->point->ins);
		fflush(stdout);
		profile = profile->next;
	} while (profile);
	profile = iTmp;
	if(buildPolyAbort == true)
		printf("\n------BUILD POLY ABORTED------\n");
#endif


	/* l'algoritmo richiede che il primo punto appartenga alla mesh 1 */
	/*
	  while (profile->queueMesh != EM1FM2) {
	    iTmp = profile;
	    while (iTmp->next) {
	      iTmp = iTmp->next;
	    }
	    iTmp->next = profile;
	    profile = profile->next;
	    iTmp->next->next = NULL;
	  }
	 */

#if DEBUG_GLUE
	printf("<<----------------------------BUILD P\n");
#endif
	if(buildPolyAbort == false){
		*count = nInt;
		*num = numTmp;
		return profile;
	}
	else{
		*count = nInt;
		*num = numTmp;
		return NULL;
	}

}

/* Funzione che verifica se il punto di intersezione (i) appartiene alla face (f).
   Nel caso interFace sia NULL allora il punto deve appartenere esclusivamente
   a un edge (e) della face.
   Altrimenti può essere anche interno alla face. */
bool gen_checkIntersection(Mod_SubdivMesh *mesh, Vertex iv, int f, int *e,
		q_point *pEdge, q_point *pFace) {

	int i;
	q_point *tmp;
	bool test;

	test = false;

	/* Ricerca sugli edge */
	tmp = pEdge;
	do {

		if ((float)iv.x == (float)tmp->v.x &&
				(float)iv.y == (float)tmp->v.y &&
				(float)iv.z == (float)tmp->v.z ) {

			/* Se è lo stesso punto controllo l'edge */
			for (i=0; i < mesh->face[f].nVert; i++) {
				//printf("face %d, nVert %d\n",f,mesh->face[f].nVert);
				//printf("v: %g %g %g -E: %d - %d\n",tmp->v.x,tmp->v.y,tmp->v.z,mesh->face[f].edge[i],tmp->indexEdge);
				if (mesh->face[f].edge[i] == tmp->indexEdge) {
					if (e) *e = tmp->indexEdge;
					test = true;
					break;
				}
			}
			if (test) break;
		}

		tmp = tmp->next;
	} while (tmp);

	if (test) return test;

	/* Ricerca nelle face */
	if (pFace) {
		tmp = pFace;
		do {

			if ((float)iv.x == (float)tmp->v.x &&
					(float)iv.y == (float)tmp->v.y &&
					(float)iv.z == (float)tmp->v.z ) {
				//printf("v: %g %g %g -F: %d - %d\n",tmp->v.x,tmp->v.y,tmp->v.z,f,tmp->indexFace);
				/* Se è lo stesso punto controllo la face */
				if (f == tmp->indexFace) {
					test = true;
					break;
				}
			}

			tmp = tmp->next;
		} while (tmp);
	}

	return test;
}

/* Procedura per l'inserimento di un profilo poligonale in una mesh,
   in modo da creare nuove face e nuovi edge. */
Mod_SubdivMesh* gen_insertProfile(Mod_SubdivMesh *mesh, int howMesh, i_point **profiles,
		int n, int current, int size, q_point *interEdge, q_point *interFace) {

	int i, j, h, e, f, eI, eO, pv, nx, k1, k2, k3;
	int nI, v1, Iv1, v2, Iv2;
	int subPatch;
	int k;
	Vertex p0, p1, v;
	bool close, sameEdge, t, test, test2;
	i_point *poly[MAXVAL];
	i_point *tmp, *startProfile, *tmpp, *tmpn;
	q_point *qtmp;
	Mod_SubdivMesh *new_mesh;
	i_point **profile = &(profiles[current]);
	i_point *tmp2;


#if DEBUG_GLUE
	printf("INSERT P---------------------------->>\n");
#endif


	startProfile = *profile;
	close = false;    /* indica che la poligonale si sta chiudendo,
	                       evitando di processare la face sbagliata */

	/* Come prima cosa si controlla se qualcuno dei punti trovati coincide
	     con un vertice della mesh, per evitare l'inserimento di doppioni.
	     Sarà assegnato loro il valore negativo dell'indice del vertice
	     che duplicano. */
	tmp = *profile;
	do {
		tmp->indexV = 0;
		tmp = tmp->next;
	} while (tmp);

	nI = 0;
	for (i=1; i <= mesh->nVert; i++) {
		tmp = *profile;
		do {
			if ( ((float)tmp->point->v.x == (float)mesh->vert[i].x) &&
					((float)tmp->point->v.y == (float)mesh->vert[i].y) &&
					((float)tmp->point->v.z == (float)mesh->vert[i].z) ) { tmp->indexV = -i; nI += 1; }
			tmp = tmp->next;
		} while (tmp);
	}

	/* Aggiornamento della mesh */
	new_mesh = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
	if (!new_mesh) ErrorMessage();
	new_mesh->nVert = mesh->nVert + (n - nI);
	new_mesh->vert  = (Vertex*) malloc((new_mesh->nVert + 1) * sizeof(Vertex));
	if (!new_mesh->vert) ErrorMessage();


	/* ... copia dei vertici ... */
	for (i=1; i <= mesh->nVert; i++) {
#if DEBUG_GLUE
		if (i==1) printf("Nuova lista vertici:\n");
#endif
		new_mesh->vert[i].x = mesh->vert[i].x;
		new_mesh->vert[i].y = mesh->vert[i].y;
		new_mesh->vert[i].z = mesh->vert[i].z;
		new_mesh->vert[i].tan = mesh->vert[i].tan;
		new_mesh->vert[i].ins = mesh->vert[i].ins;
#if DEBUG_GLUE
		printf("v %f %f %f\n",new_mesh->vert[i].x,
				new_mesh->vert[i].y,new_mesh->vert[i].z);
#endif
	}

	tmp = *profile;
	do {
		if (tmp->indexV == 0) {
			tmp->indexV = i;
			new_mesh->vert[i].x = tmp->point->v.x;
			new_mesh->vert[i].y = tmp->point->v.y;
			new_mesh->vert[i].z = tmp->point->v.z;
			new_mesh->vert[i].tan = tmp->point->tan;
			new_mesh->vert[i].ins = tmp->point->ins;
#if DEBUG_GLUE
			printf("v %f %f %f\n",new_mesh->vert[i].x,new_mesh->vert[i].y,new_mesh->vert[i].z);
#endif
			i++;
		}
		tmp = tmp->next;
	} while (i <= new_mesh->nVert);


	/* Alcune delle vecchie faccie saranno suddivise dalla poligonale,
	     contando i punti tra edge e edge si può determinare quante nuove face
	     saranno create:
	     - >0  : la face sara divisa in due parti;
	     - =0  : se l'edge di ingresso è diverso da quello di uscita (ATTENZIONE:
	             per evitare errori, viene controllato che non esista un edge della
	             mesh su cui giacciono entrambi i punti) allora la face sarà
	             suddivisa altrimenti la poligonale percorre un edge della face
	             senza attraversarla. */
	tmpp = (*profile);
	tmp = (*profile)->next;
	f = 0;                             /* nuove face */
	i = 0;                             /* numero punti intermedi */

	//int nSplit[mesh->nFace+1];          /* contatore numero di split per ogni faccia */
	vector<int> nSplit(mesh->nFace+1);
	for(k=0;k<=mesh->nFace;k++)
		nSplit[k]=0;

	do {
		/* Le facce in tangenza sono già state inserite, quindi posso
		 * evitare di considerare i punti in tangenza consecutivi, se
		 * non sono su degli edge della mesh originale. */
		if (tmp->point->tan==1 && tmpp->point->tan==1 && !(tmp->point->ins==1 && tmpp->point->ins==1)){
			tmpp = tmp;
			tmp = tmp->next;
			i = 0;
			if(tmp==NULL) break;
			continue;
		}

		if (tmp->queueMesh != howMesh) { /* sono punti interni alla face */

			j = 1;
			qtmp = interEdge;
			do { /* doppio controllo: non deve essere un punto ottenuto
	              dall'intersezione di due edge */

				if ((float)qtmp->v.x == (float)tmp->point->v.x &&
						(float)qtmp->v.y == (float)tmp->point->v.y &&
						(float)qtmp->v.z == (float)tmp->point->v.z) { j = 0; break; }
				qtmp = qtmp->next;
			} while (qtmp);


			if (j) {
				i += 1;
				tmp = tmp->next;

			} else {
				p0.x = tmpp->point->v.x;
				p0.y = tmpp->point->v.y;
				p0.z = tmpp->point->v.z;
				p1.x = tmp->point->v.x;
				p1.y = tmp->point->v.y;
				p1.z = tmp->point->v.z;
				/* si verifica se la face verrà suddivisa */
				t = gen_onSameEdge(mesh, interEdge, p0, p1);
				//if(!t) printf("1- faccia suddivisa da tmpp %d tmp %d\n",tmpp->indexV,tmp->indexV);
				if ( (i > 0) || !t ){
					f += 1;
					//Aggiorno contatore nSplit
					if( tmpp->point->tan!=1 && tmp->point->tan!=1 && (
							mesh->edge[tmpp->point->indexEdge].neigh[0] == mesh->edge[tmp->point->indexEdge].neigh[0] ||
							mesh->edge[tmpp->point->indexEdge].neigh[0] == mesh->edge[tmp->point->indexEdge].neigh[1] ))
						nSplit[mesh->edge[tmpp->point->indexEdge].neigh[0]]++;
					else if(tmpp->point->tan!=1 && tmp->point->tan!=1 && (
							mesh->edge[tmpp->point->indexEdge].neigh[1] == mesh->edge[tmp->point->indexEdge].neigh[0] ||
							mesh->edge[tmpp->point->indexEdge].neigh[1] == mesh->edge[tmp->point->indexEdge].neigh[1])){
						nSplit[mesh->edge[tmpp->point->indexEdge].neigh[1]]++;
					}
				}
				tmpp = tmp;
				tmp = tmp->next;
				i = 0;
			}


		} else {
			p0.x = tmpp->point->v.x;
			p0.y = tmpp->point->v.y;
			p0.z = tmpp->point->v.z;
			p1.x = tmp->point->v.x;
			p1.y = tmp->point->v.y;
			p1.z = tmp->point->v.z;
			/* si verifica se la face verrà suddivisa */
			t =gen_onSameEdge(mesh, interEdge, p0, p1);
			//if(!t) printf("2- faccia suddivisa da tmpp %d tmp %d\n",tmpp->indexV,tmp->indexV);
			if ( (i > 0) || !t ){
				f += 1;
				//Aggiorno contatore nSplit
				if(tmpp->point->tan!=1 && tmp->point->tan!=1 && (
					mesh->edge[tmpp->point->indexEdge].neigh[0] == mesh->edge[tmp->point->indexEdge].neigh[0] ||
					mesh->edge[tmpp->point->indexEdge].neigh[0] == mesh->edge[tmp->point->indexEdge].neigh[1])){
					nSplit[mesh->edge[tmpp->point->indexEdge].neigh[0]]++;
				}
				else if(tmpp->point->tan!=1 && tmp->point->tan!=1 && (
						mesh->edge[tmpp->point->indexEdge].neigh[1] == mesh->edge[tmp->point->indexEdge].neigh[0] ||
						mesh->edge[tmpp->point->indexEdge].neigh[1] == mesh->edge[tmp->point->indexEdge].neigh[1])){
					nSplit[mesh->edge[tmpp->point->indexEdge].neigh[1]]++;
				}
			}
			tmpp = tmp;
			tmp = tmp->next;
			i = 0;
		}

	} while (tmp);

	/* va considerato anche la chiusura della poligonale */
	p0.x = tmpp->point->v.x;
	p0.y = tmpp->point->v.y;
	p0.z = tmpp->point->v.z;
	p1.x = (*profile)->point->v.x;
	p1.y = (*profile)->point->v.y;
	p1.z = (*profile)->point->v.z;
	t =gen_onSameEdge(mesh, interEdge, p0, p1);
	//if(!t) printf("3- faccia suddivisa da tmpp %d sp %d\n",tmpp->indexV,(*profile)->indexV);
	if ( (i > 0) || !t ){
		f += 1;
		/*
	     Aggiorno contatore nSplit
	     Se p0 e p1 sono sullo stesso edge non devo fare suddivisioni aggiuntive
	     (nSplit conteggia il numero di suddivisioni nella faccia e non il numero di facce)
		 */
		if(!t){
			tmp = *profile;
			if(tmpp->point->tan!=1 && (*profile)->point->tan!=1 && (
				mesh->edge[tmpp->point->indexEdge].neigh[0] == mesh->edge[tmp->point->indexEdge].neigh[0] ||
				mesh->edge[tmpp->point->indexEdge].neigh[0] == mesh->edge[tmp->point->indexEdge].neigh[1] ))
				nSplit[mesh->edge[tmpp->point->indexEdge].neigh[0]]++;
			else if(tmpp->point->tan!=1 && (*profile)->point->tan!=1 && (
					mesh->edge[tmpp->point->indexEdge].neigh[1] == mesh->edge[tmp->point->indexEdge].neigh[0] ||
					mesh->edge[tmpp->point->indexEdge].neigh[1] == mesh->edge[tmp->point->indexEdge].neigh[1] )){
				nSplit[mesh->edge[tmpp->point->indexEdge].neigh[1]]++;
			}
		}
	}
/*
	printf("DEBUG PUNTATORI\n");
	tmp = startProfile;
	while(tmp){
		printf("tmp:%d tan:%d ins:%d\n",tmp->indexV,tmp->point->tan,tmp->point->ins);
		tmp = tmp->next;
	}
*/

	/*
	    MORENO
	    Quando incremento il contatore per le nuove facce, posso salvare l'informazione
	    indexFace in una struttura (es. vettore): così so quante volte devo suddividere
	    ogni faccia.
	    Quando lavorerò sull'i-esima faccia, controllerò questo vettore per verificare
	    se sono necessarie altre suddivisioni. Se si, dovrò effettuare le altre suddivisioni.
	    Dovrò verificare su quale parte della faccia, che è già stata suddivisa, devo
	    fare la nuova suddivisione.
	    Per fare la suddivisione,devo passare alla faccia successiva solo se non ci sono altre
	    divisioni da fare per la faccia in cui mi trovo.
	    ogni elemento del vettore mi dice quante volte va suddivisa ciascuna faccia.
	 */

#if DEBUG_GLUE
	printf("Cross Edge %d => New face\n",f);
#endif


	new_mesh->nFace = mesh->nFace + f;
	new_mesh->face = (Face*) malloc((new_mesh->nFace + 1) * sizeof(Face));
	if (!new_mesh->face) ErrorMessage();

	/* ... copia delle faccette e separazione
	     di quelle interessate dalla poligonale. */
	f = 1;
	for (i=1; i <= mesh->nFace; i++) {

		// le facce tangenti vanno ricopiate
		if(mesh->face[i].tan==1){
			new_mesh->face[f].nVert = mesh->face[i].nVert;
			new_mesh->face[f].tan = 1;
			for(j=0;j<mesh->face[i].nVert;j++)
				new_mesh->face[f].vert[j] = mesh->face[i].vert[j];
			f++;
			continue;
		}

		//azzero il contatore di suddivisioni effettuate per questa faccia
		k=0;
		/* si controlla se la face vecchia è da suddividere,
	       è importante evitare di suddividere una face un cui edge è toccato
	       dalla poligonale */
		e = 2;
		test = false;
		tmp = startProfile;
		tmpp = tmp;
		tmpn = tmpp->next;
		k1 = 0;
		while(tmpn!=NULL){
			if((tmpn->point->tan==1 && tmpn->point->ins==1)||(tmpn->point->tan!=1 && gen_checkIntersection(mesh,tmpn->point->v,i,NULL,interEdge,NULL)))
				tmpp = tmpn;
			tmpn = tmpn->next;
		}
		tmpn = tmp;
		while(tmpn){
			// printf("valuto punto %d tan: %d  ins: %d\n",tmpn->indexV,tmpn->point->tan,tmpn->point->ins);
			tmpn = tmpn->next;
			if(tmpn==NULL && k1==0){
				k1 = 1;
				tmpn = startProfile;
			}
			if((tmpn!=NULL)&&((tmpn->point->tan==1 && tmpn->point->ins==1)||(tmpn->point->tan!=1 && gen_checkIntersection(mesh,tmpn->point->v,i,NULL,interEdge,NULL))))
				break;
		}
		while(tmp){
			test2 = false;
			// printf("valuto punto %d tan: %d  ins: %d\n",tmp->indexV,tmp->point->tan,tmp->point->ins);
			// printf("tmpp: %d  tmp: %d tmpn: %d\n",tmpp->indexV,tmp->indexV,tmpn->indexV);
			if(tmp->point->tan==1){
				// verifico che appartenga alla faccia i
				k2 = mesh->mod_find_in_vert(tmp->point->v);
				if(mesh->mod_find_in_face(mesh->face,i,k2) < mesh->face[i].nVert){
					// verifico quale tra tmpp e tmpn appartiene alla faccia i
					pv = mesh->mod_find_in_vert(tmpp->point->v);
					nx = mesh->mod_find_in_vert(tmpn->point->v);
					if(pv!=-1){
						k1 = mesh->mod_find_in_face(mesh->face,i,pv);
						if(k1<mesh->face[i].nVert){
							if(tmpp->point->tan == 1 && k1!=k2){
								// verifico che non vi sia un edge tangente che collega direttamente tmpp a tmp
								for(int v=1;v<=mesh->nEdge;v++){
									if(mesh->edge[v].tan==1){
										if((abs(mesh->edge[v].vert[0])==pv && abs(mesh->edge[v].vert[1])==k2) ||
											(abs(mesh->edge[v].vert[1])==pv && abs(mesh->edge[v].vert[0])==k2)	){
											test2 = true;
										}
									}
								}
								// verifico di non andare da tmpp a tmp attraverso punti tangenti
								if((tmpp->next!=NULL && tmpp->next->point->tan==1 && tmpp->next->indexV!=tmp->indexV)||(tmpp->next==NULL && startProfile->point->tan==1 && startProfile->indexV!=tmp->indexV))
									test2 = true;
							}
							if(!test2 && (tmpp->point->tan==1 || (tmpp->point->tan!=1 && gen_checkIntersection(mesh, tmpp->point->v, i, NULL, interEdge, NULL)))){
								test = true;
								// printf("1- preso punto %d tan: %d  ins: %d\n",tmp->indexV,tmp->point->tan,tmp->point->ins);
								e -= 1;
							}
						}
					}
					else if(pv==-1){
						if (gen_checkIntersection(mesh, tmpp->point->v, i, NULL, interEdge, NULL)){
							e -= 1;
						}
					}
					if(nx!=-1){
						k3 = mesh->mod_find_in_face(mesh->face,i,nx);
						if(k3<mesh->face[i].nVert){
							if(tmpn->point->tan == 1){
								// verifico che non vi sia un edge tangente che collega direttamente tmp a tmpn
								for(int v=1;v<=mesh->nEdge;v++){
									if(mesh->edge[v].tan==1){
										if((abs(mesh->edge[v].vert[0])==k2 && abs(mesh->edge[v].vert[1])==nx) ||
										   (abs(mesh->edge[v].vert[1])==k2 && abs(mesh->edge[v].vert[0])==nx)	){
											test2 = true;
										}
									}
								}
								// verifico di non andare da tmp a tmpn attraverso punti tangenti
								if((tmp->next!=NULL && tmp->next->indexV != tmpn->indexV)||(tmp->next==NULL && startProfile->indexV != tmpn->indexV))
									test2 = true;
							}
							if(!test2 && (tmpn->point->tan==1 || (tmpn->point->tan!=1 && gen_checkIntersection(mesh, tmpn->point->v, i, NULL, interEdge, NULL)))){
								test = true;
								// printf("2- preso punto %d tan: %d  ins: %d\n",tmp->indexV,tmp->point->tan,tmp->point->ins);
								e -= 1;
							}
						}
					}
					else if(nx==-1){
						if (gen_checkIntersection(mesh, tmpn->point->v, i, NULL, interEdge, NULL)){
							e -= 1;
						}
					}
				}
				/*
				for(int v=0;v<mesh->face[i].nVert;v++){
					if(mesh->vert[mesh->face[i].vert[v]].x==tmp->point->v.x &&
					   mesh->vert[mesh->face[i].vert[v]].y==tmp->point->v.y &&
					   mesh->vert[mesh->face[i].vert[v]].z==tmp->point->v.z ){

						pv = mesh->mod_find_in_vert(tmpp->point->v);
						nx = mesh->mod_find_in_vert(tmpn->point->v);
						k1 = mesh->mod_find_in_face(mesh->face,i,pv);
						k2 = mesh->mod_find_in_face(mesh->face,i,nx);
						// deve essere ins e precedere o seguire un altro punto ins della faccia i,
						// o essere ins e precedere o seguire un punto non tangente della faccia i,escludendo i punti interni alla faccia
						if ((tmp->point->ins==1 &&
							((((tmpp->point->tan==1 && tmpp->point->ins==1)||tmpp->point->tan!=1) && k1<mesh->face[i].nVert)||
							 (((tmpn->point->tan==1 && tmpn->point->ins==1)||tmpn->point->tan!=1) && k2<mesh->face[i].nVert)))){
							test = true; 	// ho preso un punto tangente
							//printf("preso punto %d tan: %d  ins: %d\n",tmp->indexV,tmp->point->tan,tmp->point->ins);
							count++;
							e -= 1;
						}
						break;

					}
				}
*/
			}
			else if (gen_checkIntersection(mesh, tmp->point->v, i, NULL, interEdge, NULL)){
				e -= 1;
			}

			tmpp = tmp;
			while(tmp){
				tmp = tmp->next;
				if(tmp==NULL) break;
				if((tmp->point->tan==1 && tmp->point->ins==1)||(tmp->point->tan!=1 && gen_checkIntersection(mesh,tmp->point->v,i,NULL,interEdge,NULL)))
					break;
			}
			while(tmpn){
				if(tmp==NULL) break;
				if(tmpn->indexV!=tmp->indexV && ((tmpn->point->tan==1 && tmpn->point->ins==1)||(tmpn->point->tan!=1 && gen_checkIntersection(mesh,tmpn->point->v,i,NULL,interEdge,NULL))))
					break;
				tmpn = tmpn->next;
				if(tmpn==NULL) tmpn = startProfile;
			}

		};

		if(test && e==1) e = 2;  // non occorre inserire il punto tangente, c'è già


#if DEBUG_GLUE
		if (i == 1) printf("Nuova lista facce:\n");
#endif

		if (e > 0) { /* face da ricopiare */

			Iv1 = -1;
			if (e==1) { /* se la face è toccata da un punto lungo il bordo,
	                     questo va inserito */

				tmp = startProfile;
				do {

					v.x = tmp->point->v.x;
					v.y = tmp->point->v.y;
					v.z = tmp->point->v.z;

					for (e=0; e < mesh->face[i].nVert; e++) {

						p0.x = mesh->vert[mesh->face[i].vert[e]].x;
						p0.y = mesh->vert[mesh->face[i].vert[e]].y;
						p0.z = mesh->vert[mesh->face[i].vert[e]].z;
						p1.x = mesh->vert[mesh->face[i].vert[(e+1) % mesh->face[i].nVert]].x;
						p1.y = mesh->vert[mesh->face[i].vert[(e+1) % mesh->face[i].nVert]].y;
						p1.z = mesh->vert[mesh->face[i].vert[(e+1) % mesh->face[i].nVert]].z;

						if (gen_pointDsegment(v, p0, p1, 0)) {                          /* PROBLEMA POTENZIALE */
#if DEBUG_GLUE
							printf("\tAdd 1 vertex = (%g %g %g)\n",v.x,v.y,v.z);
#endif
							Iv1 = (e + 1) % mesh->face[i].nVert;
							break;
						}
					}
					if (Iv1 > 0) break;
					tmp = tmp->next;
				} while (tmp);
			}


			if (Iv1 > 0){
				new_mesh->face[f].nVert = mesh->face[i].nVert + 1;
				/*non c'è una separazione della faccia,il numero di facce finale sarà quello calcolato -1*/
				new_mesh->nFace--;  /*una locazione di memoria non verrà utilizzata*/
			}
			else new_mesh->face[f].nVert = mesh->face[i].nVert;

#if DEBUG_GLUE
			printf("Face no.%d  NVertices %d  Vertices ",f,new_mesh->face[f].nVert);
#endif

			e = 0;  j = 0;
			do {

				if (j != Iv1) {
					new_mesh->face[f].vert[e] = mesh->face[i].vert[j];
					j++;
				} else {
					new_mesh->face[f].vert[e] = fabs(tmp->indexV);
					Iv1 -= 1;
				}

#if DEBUG_GLUE
				printf("%d ",new_mesh->face[f].vert[e]);
#endif

				e++;
			} while (e < new_mesh->face[f].nVert);

#if DEBUG_GLUE
			printf("\n");
#endif

			new_mesh->face[f].tan = mesh->face[i].tan;

			f++;

		}
		else { /* face da suddividere */

			eI = eO = 0;
			nI = 0;

			/* Come prima cosa bisogna individuare uno degli edge della face
	         attraversato dalla poligonale, li sarà da inserire il primo
	         punto di taglio della stessa ... */
			tmp = startProfile;

			do {
				if (gen_checkIntersection(mesh, tmp->point->v, i, &e, interEdge, NULL)) {

					// tra i punti tan considero solo i punti ins
					if(tmp->point->tan==1 && tmp->point->ins==0){
						tmpp = tmp;
						tmp = tmp->next;
						if(!tmp) break;
						continue;
					}

					/* Usando la lista di intersezioni relativa ai lati di questa mesh verifico se il punto V è stato generato da un lato della faccia I che mi appresto a suddividere.
						Si memorizza anche il lato in questione.

						Se il test da esito positivo allora si effettua lo stesso controllo per il punto V+1, la ricerca in questo caso sarà effettuata su entrambe le liste.
					 */
					/* si verifica che anche il punto successivo faccia parte
	             della face, potrebbe essere il caso di un vertice della face
	             che "tocca" la poligonale in un punto non interno ad essa. */

					if (tmp->next) tmpn = tmp->next;
					else tmpn = startProfile;

					if (gen_checkIntersection(mesh, tmpn->point->v, i, NULL, interEdge, interFace)) {
						if ((tmp == *profile && !close) || tmp != startProfile) {

							if (tmp == *profile && !close) { close = true; }
							else if (!close) { /* Se il punto di inizio non coincide con
	                                      l'inizio della poligonale, si stabilisce
	                                      un nuovo punto di inizio, in questo modo
	                                      non ci saranno problemi con la chiusura
	                                      della poligonale. */

								close = true;

								startProfile = tmp;

								tmpp->next = NULL;
								tmpp = tmp;

								while (tmpp->next) {
									tmpp = tmpp->next;
								}
								tmpp->next = *profile;

							}

#if DEBUG_GLUE
							printf("\tEdge Input: %d  -->  ",e); fflush(stdout);
#endif
							eI = e;
							poly[nI] = tmp;  nI += 1;
							break;
						}
					}
				}
				if (eI) break;

				tmpp = tmp;
				tmp = tmp->next;

			} while (tmp);

			/* .... poi si procede cercando l'edge in cui la poligonale abbandona
	         la face, quello sarà il punto di uscita della face. */

			/* si parte a cercare dall'elemento successivo o di nuovo dall'inizio */
			if(tmp) tmp = tmp->next;

			do {
				if (!tmp) tmp = startProfile;
				poly[nI] = tmp;
				nI++;


				if (gen_checkIntersection(mesh, tmp->point->v, i, &e, interEdge, NULL)) {

#if DEBUG_GLUE
					printf("Edge Output: %d => ",e);
#endif
					eO = e;
					break;
				}
				if (eO) break;
				tmp = tmp->next;
			} while (!eO);  /* non si esce sino a che non si trova il punto,
	                         se la lista è vuota si ricomincia */

#if DEBUG_GLUE
			//printf("\nEdge in: %d %d     Edge out: %d %d\n",mesh->edge[eI].vert[0],mesh->edge[eI].vert[1],mesh->edge[eO].vert[0],mesh->edge[eO].vert[1]);
			printf("New Vertex: %d = ",nI);
#endif

			/* Ora si ha a disposizione l'indice dell'edge di ingresso (eI),
	         l'indice dell'edge di uscita (eO), il numero di punti da inserire
	         nella face (nI) e i puntatori a tali punti (poly[0 <= j < nI]). */
#if DEBUG_GLUE
			for (j=0; j < nI; j++) {
				printf("(%g %g %g) ",poly[j]->point->v.x,poly[j]->point->v.y,
						poly[j]->point->v.z);
			}
			printf("\n");
#endif


			/* Per mantenere coerenti le normali dei due patch si procede
	         nel seguente modo: si determina il primo vertice, nella sequenza
	         dei vertici della face, dopo il punto di uscita della poligonale
	         dalla face, si prosegue sino al punto di ingresso e ci si collega
	         il pezzo di poligonale; poi si trova il primo vertice dopo il punto
	         di ingresso, si prosegue sino al punto di uscita e ci si collega
	         la poligonale al contrario. */

			for (e=0; e < mesh->face[i].nVert; e++) { /* il vertice successivo al
	                                                   punto di uscita */

				if ((mesh->face[i].vert[e] == mesh->edge[eO].vert[0] &&
						mesh->face[i].vert[(e+1) % mesh->face[i].nVert] ==
								mesh->edge[eO].vert[1]) ||
						(mesh->face[i].vert[e] == mesh->edge[eO].vert[1] &&
								mesh->face[i].vert[(e+1) % mesh->face[i].nVert] ==
										mesh->edge[eO].vert[0])) {

					if (mesh->face[i].vert[(e + 1) % mesh->face[i].nVert] ==
							fabs(poly[(nI - 1)]->indexV) ) e = (e + 1) % mesh->face[i].nVert;
					Iv1 = (e + 1) % mesh->face[i].nVert;
					v1 = mesh->face[i].vert[Iv1];
					break;
				}
			}

			for (e=0; e < mesh->face[i].nVert; e++) { /* il vertice successivo al
	                                                   punto di ingresso */

				if ((mesh->face[i].vert[e] == mesh->edge[eI].vert[0] &&
						mesh->face[i].vert[(e+1) % mesh->face[i].nVert] ==
								mesh->edge[eI].vert[1]) ||
						(mesh->face[i].vert[e] == mesh->edge[eI].vert[1] &&
								mesh->face[i].vert[(e+1) % mesh->face[i].nVert] ==
										mesh->edge[eI].vert[0])) {

					if (mesh->face[i].vert[(e + 1) % mesh->face[i].nVert] ==
							fabs(poly[0]->indexV) ) e = (e + 1) % mesh->face[i].nVert;
					Iv2 = (e + 1) % mesh->face[i].nVert;
					v2 = mesh->face[i].vert[Iv2];
					break;
				}
			}

			sameEdge = false;
			//usare gli indici degli edge eI eO invece di fare check di tolleranza
			/*
	    Si può usare una tolleranza per la pointDsegment scelta come frazione della distanza tra il punto di ingresso
	    e il punto di uscita dalla faccia. In questo modo non dovrebbe dar problemi.
	    original tollerance 0.02 --> 0.000002
			 */
			/*double dToll;
	    dToll = 0.7*sqrt( (poly[0]->point->v.x - poly[(nI-1)]->point->v.x )*(poly[0]->point->v.x - poly[(nI-1)]->point->v.x) +
	                      (poly[0]->point->v.y - poly[(nI-1)]->point->v.y )*(poly[0]->point->v.y - poly[(nI-1)]->point->v.y) +
	                      (poly[0]->point->v.z - poly[(nI-1)]->point->v.z )*(poly[0]->point->v.z - poly[(nI-1)]->point->v.z) );

			 */

			if(eI==eO)
				sameEdge=true;

			/* Vecchio codice:
			 * for (e=0; e < mesh->face[i].nVert; e++) {  se il punto di ingresso e di
	                                                   uscita appartengono allo
	                                                   stesso edge allora un patch
	                                                   sarà formato solo da punti
	                                                   della poligonale.  */
			/*    v.x = poly[0]->point->v.x;
	        v.y = poly[0]->point->v.y;
	        v.z = poly[0]->point->v.z;

	        p0.x = mesh->vert[mesh->edge[mesh->face[i].edge[e]].vert[0]].x;
	        p0.y = mesh->vert[mesh->edge[mesh->face[i].edge[e]].vert[0]].y;
	        p0.z = mesh->vert[mesh->edge[mesh->face[i].edge[e]].vert[0]].z;
	        p1.x = mesh->vert[mesh->edge[mesh->face[i].edge[e]].vert[1]].x;
	        p1.y = mesh->vert[mesh->edge[mesh->face[i].edge[e]].vert[1]].y;
	        p1.z = mesh->vert[mesh->edge[mesh->face[i].edge[e]].vert[1]].z;

	        if (pointDsegment(v, p0, p1,dToll)) {  controllato INPUT */

			/*        v.x = poly[(nI - 1)]->point->v.x;
	          v.y = poly[(nI - 1)]->point->v.y;
	          v.z = poly[(nI - 1)]->point->v.z;
	          if (pointDsegment(v, p0, p1, dToll)) {  si controlla OUTPUT */
			/*          sameEdge = TRUE; break;
	          }
	        }
	      }
			 */
			subPatch = 0;
			if (sameEdge) { /* se INPUT e OUTPUT risultano sullo stesso edge, allora
	                         si determina quale patch risulta composto dai soli
	                         vertici della poligonale */

				/* se pINPUT appartine al segmento (pOUTPUT-I° punto dopo pOUTPUT)
	            allora il primo patch sarà composto dai soli vertici del profilo
	                   [subPatch = 1];
	            altrimenti il secondo patch sarà composto dai soli vertici del
	                       profilo in ordine inverso [subPatch = 2]. */
				v.x = poly[0]->point->v.x;
				v.y = poly[0]->point->v.y;
				v.z = poly[0]->point->v.z;
				p0.x = poly[(nI - 1)]->point->v.x;
				p0.y = poly[(nI - 1)]->point->v.y;
				p0.z = poly[(nI - 1)]->point->v.z;
				p1.x = mesh->vert[v1].x;
				p1.y = mesh->vert[v1].y;
				p1.z = mesh->vert[v1].z;
				if (gen_pointDsegment(v, p0, p1, 0.000002)) subPatch = 1;
				else subPatch = 2;
			}


			/* PRIMO PATCH: dall'uscita della poligonale all'ingresso ... */
			e = 0;
#if DEBUG_GLUE
			printf("Face no.%d  Vertices ",f);
#endif
			/* ... prima i vertici della face .... */
			if (subPatch != 1) {
				do {

					new_mesh->face[f].vert[e] = mesh->face[i].vert[Iv1];
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[f].vert[e]);
#endif

					e++;
					Iv1 = (Iv1 + 1) % mesh->face[i].nVert;
				} while (mesh->face[i].vert[Iv1] != v2);
			}

			/* ... poi i vertici della poligonale. */
			if (subPatch != 1 || nI > 2) {
				j = 0;
				if(poly[j]->point->tan == 1) j=1; //i punti tangenti del profilo appartengono alla faccia, e sono quindi già stati inseriti
				for (; j < nI; j++) {
					new_mesh->face[f].vert[e] = fabs(poly[j]->indexV);
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[f].vert[e]);
#endif
					e++;
				}
			}

			new_mesh->face[f].nVert = e;
			new_mesh->face[f].tan = 0;

#if DEBUG_GLUE
			printf("  NVertices %d\n", new_mesh->face[f].nVert);
#endif

			if (subPatch != 1 || nI > 2){
				/*MORENO: devo aggiornare gli index face dei punti dei profili successivi.
	        Per ogni punto che era intersezione in una generica faccia h, con h>=i, devo incrementare
	        l'index face.
	        Devo aggiornare l'indice anche nella lista interface
	        Devo aggiornare l'indexEdge dei profili e l'indexEdge in interEdge
				 */
				for(j=0;j<size;j++){
					tmp2 = profiles[j];     //profilo successivo
					while(tmp2!=NULL){
						if(tmp2->queueMesh != howMesh && tmp2->point->indexFace >= f){  //punto interno a una face con indexFace >= f?
							// printf("p: %g %g %g -F %d --> %d\n",tmp2->point->v.x,tmp2->point->v.y,tmp2->point->v.z,tmp2->point->indexFace,tmp2->point->indexFace+1);
							tmp2->point->indexFace++;               //aggiorna indexFace
						}
						tmp2=tmp2->next;
					}
				}
				f++;
			}

			/* SECONDO PATCH: dall'ingresso della poligonale all'uscita ... */
			e = 0;
#if DEBUG_GLUE
			printf("Face no.%d  Vertices ",f);
#endif
			/* ... prima i vertici della face ... */
			if (subPatch != 2) {
				do {

					new_mesh->face[f].vert[e] = mesh->face[i].vert[Iv2];
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[f].vert[e]);
#endif

					e++;
					Iv2 = (Iv2 + 1) % mesh->face[i].nVert;
				} while (mesh->face[i].vert[Iv2] != v1);
			}

			/* ... poi i vertici della poligonale in ordine inverso. */
			if (subPatch != 2 || nI > 2) {
				j = nI-1;
				if(poly[j]->point->tan == 1) j = nI-2; //i punti tangenti del profilo appartengono alla faccia, e sono quindi già stati inseriti
				for (; j >= 0; j--) {
					new_mesh->face[f].vert[e] = fabs(poly[j]->indexV);
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[f].vert[e]);
#endif
					e++;
				}
			}

			new_mesh->face[f].nVert = e;
			new_mesh->face[f].tan = 0;
#if DEBUG_GLUE
			printf("  NVertices %d\n", new_mesh->face[f].nVert);
#endif

			if (subPatch != 2 || nI > 2) f++;
		}

		//if (subPatch != 2 || nI > 2) f++;

		/*QUI HO FINITO CON QUESTA FACCIA i
	    devo controllare se sono necessarie altre suddivisioni usando nSplit[i].
	    le nuove facce,quelle dopo la suddivisione,saranno in new_mesh.
	    devo vedere quale delle ultime nSplit[i] facce che ho diviso deve essere
	    ulteriormente suddivisa. Questo lo scopro scorrendo il profilo e confrontando punti
	    con edge di faccia...
	    Dopo la prima suddivisione, se nSplit>k, cerco nel profilo
	    (continuo a scorrere il profilo, non ricomincio da capo) gli altri punti
	    che separano la faccia. Quando li trovo,vedo quale delle facce che ho
	    ottenuto, per suddivisione, dalla faccia originale è interessata da quei punti.
	    (i punti li cerco usando la stessa faccia i,non divisa, e continuando a scorrere il profilo)
	    Dopodichè, divido. Avrò due facce,una sovrascriverà quella che ho diviso ulteriormente.
	    k++;  //conta quante volte ho suddiviso la faccia
	    while(nSplit[i]>k){
	        splitFace(new_mesh,mesh,*profile,k);  //k per sapere quante delle ultime facce considerare
	        k++;
	    }
		 */
		//incremento contatore suddivisioni fatte
		k++;

		int u,r,t;
		i_point *used_points[3*MAXVAL];
		u=0;
		while(nSplit[i]>k){
			printf("La faccia %d-%d va suddivisa ulteriormente!!!\n",f-2,f-1);
			printf("nSplit = %d\n",nSplit[i]);
			printf("i = %d\n",i);
			//decremento f perchè devo lavorare sulle ultime f-k facce ottenute
			f--;
			//inizializzo used_points
			for(r=0;r<3*MAXVAL;r++){
				used_points[u]=NULL;
			}
			/* metto in un vettore i punti che ho già usato */
			printf("used_points:\n");
			for(r=0;r<nI;r++){
				used_points[u]=poly[r];
				printf("( %g %g %g )\n",used_points[u]->point->v.x,used_points[u]->point->v.y,used_points[u]->point->v.z);
				u++;
			}

			/* scorro il profilo fino a trovare gli altri punti che tagliano la faccia */
			eI = eO = 0;
			int nI2 = nI;
			nI = 0;
			close = false;
			/* Come prima cosa bisogna individuare uno degli edge della face
	         attraversato dalla poligonale, li sarà da inserire il primo
	         punto di taglio della stessa ... */
			tmp = startProfile;
			do {
				/* verifico di non aver già usato tmp */
				do{
					t=0;
					for(r=0;r<nI2;r++){
						if(tmp==used_points[r]){
							t=1;
							break;
						}
					}
					if(t==1){
						tmpp = tmp;
						tmp = tmp->next;
						if (!tmp) tmp = startProfile;
					}
				}while(t==1);


				/* Usando la lista di intersezioni relativa ai lati di questa mesh verifico
	            se il punto V è stato generato da un lato della faccia I che mi appresto a
	            suddividere. Si memorizza anche il lato in questione. */
				if (gen_checkIntersection(mesh, tmp->point->v, i, &e, interEdge, NULL)) {
					/* Se il test da esito positivo allora si effettua lo stesso controllo
	            per il punto V+1, la ricerca in questo caso sarà effettuata su entrambe le liste.
	             si verifica che anche il punto successivo faccia parte
	             della face, potrebbe essere il caso di un vertice della face
	             che "tocca" la poligonale in un punto non interno ad essa. */

					/* verifico di non aver già usato tmp->next */
					if (tmp->next) tmpn = tmp->next;
					else tmpn = startProfile;
					do{
						t=0;
						for(r=0;r<nI;r++){
							if(tmpn==used_points[r]){
								t=1;
								break;
							}
						}
						if(t==1){
							if (tmpn->next) tmpn = tmpn->next;
							else tmpn = startProfile;
						}
					}while(t==1);

					if (gen_checkIntersection(mesh, tmpn->point->v, i, NULL, interEdge, interFace)) {
						if ((tmp == *profile && !close) || tmp != startProfile) {

							if (tmp == *profile && !close) { close = true; }
							else if (!close) { /* Se il punto di inizio non coincide con
	                                      l'inizio della poligonale, si stabilisce
	                                      un nuovo punto di inizio, in questo modo
	                                      non ci saranno problemi con la chiusura
	                                      della poligonale. */
								//  printf("*profile = (%g %g %g)\n",(*profile)->point->v.x,(*profile)->point->v.y,(*profile)->point->v.z);
								//  printf("punto di inizio: (%g %g %g)\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z);
								//  printf("tmpp: (%g %g %g)\n",tmpp->point->v.x,tmpp->point->v.y,tmpp->point->v.z);

								// aggiorno il puntatore al profilo, altrimenti la lista non viene aggiornata correttamente
								*profile = startProfile;

								close = true;
								startProfile = tmp;
								tmpp->next = NULL;
								tmpp = tmp;

								while (tmpp->next) {
									tmpp = tmpp->next;
									//    printf("update tmpp: ( %g %g %g ) \n",tmpp->point->v.x,tmpp->point->v.y,tmpp->point->v.z);
								}
								tmpp->next = *profile;
								// printf("final tmpp: (%g %g %g)\n",tmpp->point->v.x,tmpp->point->v.y,tmpp->point->v.z);

							}

#if DEBUG_GLUE
							printf("\tEdge Input: %d  -->  ",e); fflush(stdout);
#endif

							eI = e;
							poly[nI] = tmp;  nI += 1;
							break;
						}
					}
				}
				if (eI) break;

				tmpp = tmp;
				tmp = tmp->next;
				if (!tmp) tmp = startProfile;

			} while (tmp);
			/* .... poi si procede cercando l'edge in cui la poligonale abbandona
	         la face, quello sarà il punto di uscita della face. */
			/* si parte a cercare dall'elemento successivo o di nuovo dall'inizio */
			tmpp = tmp;
			tmp = tmp->next;
			if (!tmp) tmp = startProfile;

			do{
				//tutti questi controlli non dovrebbero servire...seguo la sequenza del profilo fino a trovare il punto di uscita...
				printf("checking point ( %g %g %g ) ...\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z);
				//verifico di non aver già usato tmp
				do{
					t=0;
					for(r=0;r<nI2;r++){
						if(tmp==used_points[r]){
							t=1;
							printf("used_point!\n");
							r=nI2;
						}
					}
					//deve anche essere diverso dal punto di ingresso
					if(tmp==poly[0]){
						printf("tmp is the IN point!\n");
						t=1;
					}
					if(t==1){
						tmp = tmp->next;
						if (!tmp) tmp = startProfile;
					}
				}while(t==1);
				//controllo se il punto appartiene alla faccia, questo primo if forse non serve (lo avevo aggiunto io credo), da controllare
				if(gen_checkIntersection(mesh, tmp->point->v, i, NULL, interEdge, interFace)){
					poly[nI] = tmp;
					nI++;
					printf("tmp: ( %g %g %g )\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z);
					//controllo se il punto è il punto di uscita
					if (gen_checkIntersection(mesh, tmp->point->v, i, &e, interEdge, NULL)) {

#if DEBUG_GLUE
						printf("Edge Output: %d => ",e);
#endif

						eO = e;
						break;
					}
					if (eO) break;
				}
				tmp = tmp->next;
				if (!tmp) tmp = startProfile;
			} while (!eO);  /* non si esce sino a che non si trova il punto,
	                         se la lista è vuota si ricomincia */
#if DEBUG_GLUE
			printf("New Vertex: %d = ",nI);
#endif
			/* Ora si ha a disposizione l'indice dell'edge di ingresso (eI),
	         l'indice dell'edge di uscita (eO), il numero di punti da inserire
	         nella face (nI) e i puntatori a tali punti (poly[0 <= j < nI]). */

			/* vedo quale delle ultime k+1 facce che ho ottenuto per suddivisione
	            è interessata da questi punti (poly[]) */
			/* devo trovare gli indici di eI e eO,nella faccia che
	            devo suddividere ulteriormente */
			eI=-1;
			eO=-1;
			for(r=(f-k);r<=f;r++){
				printf("\nr = %d\n",r);
				for(t=0;t<new_mesh->face[r].nVert;t++){
					p0.x = new_mesh->vert[new_mesh->face[r].vert[t]].x;
					p0.y = new_mesh->vert[new_mesh->face[r].vert[t]].y;
					p0.z = new_mesh->vert[new_mesh->face[r].vert[t]].z;
					p1.x = new_mesh->vert[new_mesh->face[r].vert[(t+1) % new_mesh->face[r].nVert]].x;
					p1.y = new_mesh->vert[new_mesh->face[r].vert[(t+1) % new_mesh->face[r].nVert]].y;
					p1.z = new_mesh->vert[new_mesh->face[r].vert[(t+1) % new_mesh->face[r].nVert]].z;
					/* possibile problema dipendente dalla tolleranza*/
					if(gen_pointDsegment(poly[0]->point->v,p0,p1,0.000002))      eI = t;
					if(gen_pointDsegment(poly[nI-1]->point->v,p0,p1,0.000002))   eO = t;
				}
				if(eI!=-1 && eO!=-1){
					printf("\neI: %d",eI);
					printf("\neO: %d\n",eO);
					break;
				}
			}

#if DEBUG_GLUE
			for (j=0; j < nI; j++) {
				printf("(%g %g %g)\n",poly[j]->point->v.x,poly[j]->point->v.y,
						poly[j]->point->v.z);
			}
			printf("\n");
#endif

			/* la faccia r va suddivisa ulteriormente,la suddivido e salvo il risultato in new_mesh */
			/* eI è il vertice 0 dell'edge di ingresso, e0 è il vertice 0 dell'edge di uscita*/

			/* Per mantenere coerenti le normali dei due patch si procede
	         nel seguente modo: si determina il primo vertice, nella sequenza
	         dei vertici della face, dopo il punto di uscita della poligonale
	         dalla face, si prosegue sino al punto di ingresso e ci si collega
	         il pezzo di poligonale; poi si trova il primo vertice dopo il punto
	         di ingresso, si prosegue sino al punto di uscita e ci si collega
	         la poligonale al contrario. */

			/* il vertice successivo al punto di uscita */
			Iv1 = (eO + 1) % new_mesh->face[r].nVert;
			v1 = new_mesh->face[r].vert[Iv1];
			/* il vertice successivo al punto di ingresso */
			Iv2 = (eI + 1) % new_mesh->face[r].nVert;
			v2 = new_mesh->face[r].vert[Iv2];

			sameEdge = false;

			if(eI==eO)
				sameEdge=true;

			subPatch = 0;
			if (sameEdge) { /* se INPUT e OUTPUT risultano sullo stesso edge, allora
	                         si determina quale patch risulta composto dai soli
	                         vertici della poligonale */

				/* se pINPUT appartine al segmento (pOUTPUT-I° punto dopo pOUTPUT)
	            allora il primo patch sarà composto dai soli vertici del profilo
	                   [subPatch = 1];
	            altrimenti il secondo patch sarà composto dai soli vertici del
	                       profilo in ordine inverso [subPatch = 2]. */
				v.x = poly[0]->point->v.x;
				v.y = poly[0]->point->v.y;
				v.z = poly[0]->point->v.z;
				p0.x = poly[(nI - 1)]->point->v.x;
				p0.y = poly[(nI - 1)]->point->v.y;
				p0.z = poly[(nI - 1)]->point->v.z;
				p1.x = new_mesh->vert[v1].x;
				p1.y = new_mesh->vert[v1].y;
				p1.z = new_mesh->vert[v1].z;
				if (gen_pointDsegment(v, p0, p1, 0.000002)) subPatch = 1;
				else subPatch = 2;
			}

			/* copia della faccia r prima di modificarla */
			Face* tmpFace = (Face*)malloc(sizeof(Face));
			tmpFace->nVert = new_mesh->face[r].nVert;
			for(e=0;e<tmpFace->nVert;e++){
				tmpFace->vert[e] = new_mesh->face[r].vert[e];
			}

			/* PRIMO PATCH: dall'uscita della poligonale all'ingresso ... */
			e = 0;
#if DEBUG_GLUE
			printf("Face no.%d  Vertices ",r);
#endif
			/* ... prima i vertici della face .... */
			if (subPatch != 1) {
				do {
					new_mesh->face[r].vert[e] = tmpFace->vert[Iv1];
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[r].vert[e]);
#endif

					e++;
					Iv1 = (Iv1 + 1) % tmpFace->nVert;
				} while (tmpFace->vert[Iv1] != v2);
			}

			/* ... poi i vertici della poligonale. */
			if (subPatch != 1 || nI > 2) {
				for (j=0; j < nI; j++) {
					new_mesh->face[r].vert[e] = fabs(poly[j]->indexV);
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[r].vert[e]);
#endif
					e++;
				}
			}

			new_mesh->face[r].nVert = e;

#if DEBUG_GLUE
			printf("  NVertices %d\n", new_mesh->face[r].nVert);
#endif

			if (subPatch != 1 || nI > 2){
				/*MORENO: devo aggiornare gli index face dei punti dei profili successivi.
	        Per ogni punto che era intersezione in una generica faccia h, con h>=i, devo incrementare
	        l'index face.
	        Devo aggiornare l'indice anche nella lista interface
	        Devo aggiornare l'indexEdge dei profili e l'indexEdge in interEdge
				 */
				for(j=0;j<size;j++){
					tmp2 = profiles[j];     //profilo successivo
					while(tmp2!=NULL){
						if(tmp2->queueMesh != howMesh && tmp2->point->indexFace >= r){  //punto interno a una face con indexFace >= f?
							// printf("p: %g %g %g -F %d --> %d\n",tmp2->point->v.x,tmp2->point->v.y,tmp2->point->v.z,tmp2->point->indexFace,tmp2->point->indexFace+1);
							tmp2->point->indexFace++;               //aggiorna indexFace
						}
						tmp2=tmp2->next;
					}
				}
				f++;
			}
			/* SECONDO PATCH: dall'ingresso della poligonale all'uscita ... */
			e = 0;
#if DEBUG_GLUE
			printf("Face no.%d  Vertices ",f);
#endif
			/* ... prima i vertici della face ... */
			if (subPatch != 2) {
				do {

					new_mesh->face[f].vert[e] = tmpFace->vert[Iv2];
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[f].vert[e]);
#endif

					e++;
					Iv2 = (Iv2 + 1) % tmpFace->nVert;
				} while (tmpFace->vert[Iv2] != v1);
			}

			/* ... poi i vertici della poligonale in ordine inverso. */
			if (subPatch != 2 || nI > 2) {
				for (j=(nI - 1); j >= 0; j--) {
					new_mesh->face[f].vert[e] = fabs(poly[j]->indexV);
#if DEBUG_GLUE
					printf("%d ",new_mesh->face[f].vert[e]);
#endif
					e++;
				}
			}

			new_mesh->face[f].nVert = e;
#if DEBUG_GLUE
			printf("  NVertices %d\n", new_mesh->face[f].nVert);
#endif

			if (subPatch != 2 || nI > 2) f++;

			//incremento contatore suddivisioni fatte
			k++;
		}

	}


	*profile = startProfile;

	/* Non libero la memoria,le mesh originali possono servire per eventuale undo
	 * PER LIBERARE LA MEMORIA,NON USARE UN VETTORE PER MEMORIZZARE LE DUE MESH:
	 * USARE DUE VARIABILI DISTINTE!!!
	free(mesh->vert);  free(mesh->edge);
	free(mesh->face);  free(mesh);
	 */

	/* si eliminano dalle face i vertici duplicati */
	new_mesh = gen_eraseRepeatVinF(new_mesh);

	//Aggiorno gli indexEdge di interEdge
	for(h=1;h<=new_mesh->nEdge;h++){
		for(j=0;j<size;j++){
			tmp2 = profiles[j];     //profilo successivo
			while(tmp2!=NULL){
				p0.x = new_mesh->vert[new_mesh->edge[h].vert[0]].x;
				p0.y = new_mesh->vert[new_mesh->edge[h].vert[0]].y;
				p0.z = new_mesh->vert[new_mesh->edge[h].vert[0]].z;
				p1.x = new_mesh->vert[new_mesh->edge[h].vert[1]].x;
				p1.y = new_mesh->vert[new_mesh->edge[h].vert[1]].y;
				p1.z = new_mesh->vert[new_mesh->edge[h].vert[1]].z;
				//controllo per ogni edge della mesh se contiene un punto del profilo
				if(tmp2->queueMesh == howMesh && (gen_pointDsegment(tmp2->point->v, p0, p1, 0.000002))){
					//l'indexEdge nuovo è l'index dell'edge su cui si trova il punto
					tmp2->point->indexEdge = h;
					//printf("IE update: %g %g %g -E: %d\n",tmp2->point->v.x,tmp2->point->v.y,tmp2->point->v.z,tmp2->point->indexEdge);
				}
				tmp2=tmp2->next;
			}
		}
	}

#if DEBUG_GLUE
	printf("<<----------------------------INSERT P\n");
#endif


	return new_mesh;

}

/* Funzione per verificare se i due punti sono stati generati da
   uno stesso edge. */
bool gen_onSameEdge(Mod_SubdivMesh *mesh, q_point *edgeMesh, Vertex p, Vertex q) {

	int ip, iq, ipp, iqq;
	int edgeP[MAXVAL], edgeQ[MAXVAL];
	q_point *tmp;
	bool test;

	test = false;
	tmp = edgeMesh;
	ip = iq = 0;

	/* si determina l'insieme degli edge che ha generato p e
     l'insieme degli edge che ha generato q */
	do {

		if ((float)p.x == (float)tmp->v.x &&
				(float)p.y == (float)tmp->v.y &&
				(float)p.z == (float)tmp->v.z) {
			edgeP[ip] = tmp->indexEdge;
			ip++;
		}

		if ((float)q.x == (float)tmp->v.x &&
				(float)q.y == (float)tmp->v.y &&
				(float)q.z == (float)tmp->v.z) {
			edgeQ[iq] = tmp->indexEdge;
			iq++;
		}

		tmp = tmp->next;
	} while (tmp);

	/* questo controllo numerico potrebbe fallire,
     ma risulta utile nel caso dei cubi 2 e 2b: il punto di intersezione (5,3,2)
     non veniva attribuito anche all'edge complanare alla face, per cui non
     risultava negli insiemi */
	test = gen_pointONsegment(mesh, p, q);

	/* si verifica se l'intersezione dei due insiemi è vuota */
	for (ipp=0; ipp < ip; ipp++) {
		for (iqq=0; iqq < iq; iqq++) {
			if (edgeP[ipp] == edgeQ[iqq]) {
				test = true;
				break;
			}
		}
	}

	return test;
}

/* Funzione che verifica se esiste un edge della mesh su cui
   giacciono entrambi i punti */
bool gen_pointONsegment(Mod_SubdivMesh *mesh, Vertex p0, Vertex p1) {

	int i;
	Vertex e1, e2;
	bool test;

	test = false;

	for (i=1; i <= mesh->nEdge; i++) {
		e1.x = mesh->vert[mesh->edge[i].vert[0]].x;
		e1.y = mesh->vert[mesh->edge[i].vert[0]].y;
		e1.z = mesh->vert[mesh->edge[i].vert[0]].z;
		e2.x = mesh->vert[mesh->edge[i].vert[1]].x;
		e2.y = mesh->vert[mesh->edge[i].vert[1]].y;
		e2.z = mesh->vert[mesh->edge[i].vert[1]].z;

		if (gen_pointDsegment(p0, e1, e2, 0)) { /* p0 appartiene */

			if (gen_pointDsegment(p1, e1, e2, 0)) { /* p1 appartine */
				test = true;
				break;
			}
		}
	}

	return test;
}

/* Procedura che separa una mesh in due mesh distinte seguendo
   un determinato profilo di taglio. */
Mod_SubdivMesh* gen_splitMesh(Mod_SubdivMesh *mesh, vector<Mod_SubdivMesh*> *nM, i_point **profiles, int k) {

	// k è il numero di profili
	int i, j, n, z, v1, v2;
	Mod_SubdivMesh *NmF,*tmpM;
	i_point *tmp;
	int **vertex;
	queue *faceP, *tmpFp, *tmpFpI, *tmpFpS, *edgeP, *tmpEp;
	//struct QUEUE *fP[k], *eP[k];
	vector<queue*> fP(k);
	vector<queue*> eP(k);

	for(z=0;z<k;z++){
		fP[z] = NULL;
		eP[z] = NULL;
	}

#if DEBUG_GLUE
	printf("SPLIT M---------------------------->>\n");
#endif

	/* Per ciascun profilo, si scorre il profilo di intersezione annotando tutti gli edge da cui
	     è composto. */
	n=0;
	while(n<k){
		if(profiles[n]!=NULL){
			tmp = profiles[n];  edgeP = NULL;  tmpEp = NULL;
			while (tmp) {

				v1 = fabs(tmp->indexV);
				if (tmp->next) v2 = fabs(tmp->next->indexV);
				else v2 = fabs(profiles[n]->indexV);

				for (i=1; i <= mesh->nEdge; i++) {

					if ((mesh->edge[i].tan == 0) &&	// escludo gli edge in tangenza
						((mesh->edge[i].vert[0] == v1 && mesh->edge[i].vert[1] == v2) ||
						(mesh->edge[i].vert[1] == v1 && mesh->edge[i].vert[0] == v2))) {

						if (!edgeP) {
							edgeP = (struct queue*) malloc(sizeof(struct queue));
							if (!edgeP) ErrorMessage();
							edgeP->next = NULL;
							tmpEp = edgeP;
						} else {
							tmpEp->next = (struct queue*) malloc(sizeof(struct queue));
							if (!tmpEp->next) ErrorMessage();
							tmpEp->next->next = NULL;
							tmpEp = tmpEp->next;
						}
						tmpEp->elem = i;

	#if DEBUG_GLUE
						//printf("Edge Profile's %d Vertex %d---%d\n",tmpEp->elem,v1,v2);
						//printf("%g %g %g - %g %g %g\n",mesh->vert[v1].x,mesh->vert[v1].y,mesh->vert[v1].z,mesh->vert[v2].x,mesh->vert[v2].y,mesh->vert[v2].z);
	#endif
						break;
					}
				}
				tmp = tmp->next;
			}
			if (edgeP!=NULL){
				eP[n]=edgeP;
				n++;
			}
		}
		else
			n++;
	}

	/* Per ogni profilo */
	n=0;
	while(n<k){
		if(profiles[n]!=NULL){
			/* Successivamente si carica la prima face relativa ad uno
			 degli edge appena rilevati, che non sia già stata utilizzata
			 per un altro profilo. */
			faceP = NULL;  tmpFp = NULL;
			v1 = 0;
			// Controllo che la faccia 0 dell'edge non sia già stata presa
			for(z=0;z<k;z++){
				if(z==n || !fP[z]) continue;
				// if(!fP[z]) break;
				tmpFp = fP[z];
				while (tmpFp) {
					if (mesh->edge[eP[n]->elem].neigh[0] == tmpFp->elem) {
						//printf("\nEdge %g %g %g - %g %g %g",mesh->vert[mesh->edge[eP[n]->elem].vert[0]].x,mesh->vert[mesh->edge[eP[n]->elem].vert[0]].y,mesh->vert[mesh->edge[eP[n]->elem].vert[0]].z,mesh->vert[mesh->edge[eP[n]->elem].vert[1]].x,mesh->vert[mesh->edge[eP[n]->elem].vert[1]].y,mesh->vert[mesh->edge[eP[n]->elem].vert[1]].z);
						//printf("\nVert Indexes %d %d",mesh->edge[eP[n]->elem].vert[0],mesh->edge[eP[n]->elem].vert[1]);
						v1 = 1; break;
					}
					tmpFp = tmpFp->next;
				}
				if(v1==1) break;
			}

			faceP = (struct queue*) malloc(sizeof(struct queue));
			if (!faceP) ErrorMessage();
			faceP->next = NULL;
			// Se v1=0 prendo la face 0, altrimenti prendo la face 1
			faceP->elem = mesh->edge[eP[n]->elem].neigh[v1];

	#if DEBUG_GLUE
			/*
			 for(z=0;z<k;z++){
				if(z==n) continue;
				if(!fP[z]) break;
				tmpFp = fP[z];
				while (tmpFp) {
					if (mesh->edge[eP[n]->elem].neigh[v1] == tmpFp->elem) {
						printf("\nDEBUG: Faccia già presa!!!"); break;
					}
					tmpFp = tmpFp->next;
				}
			}
			 */
			printf("\nStart filling from face %d add face ... ",faceP->elem);
	#endif

			/* A questo punto si cercano ricorsivamente tutte le face vicine alla prima,
			 escludendo dalla ricerca gli edge appartenenti alle poligonali e gli edge in tangenza.
			 Le face trovate andranno inserite in coda e si procede iterativamente. */
			tmpFpI = faceP;  /* punto da cui iniziare ad inserire le face trovate */
			tmpFp = faceP;   /* punto da cui cercare le face vicine */
			while (tmpFp != tmpFpI->next) {

				for (i=0; i < mesh->face[tmpFp->elem].nVert; i++) { /* giro degli edge */
					/* si verifica che non sia un edge di una poligonale e che non sia un edge di tangenza */
					v1 = 0;
					for(z=0;z<k;z++){
						tmpEp = eP[z];
						while (tmpEp) {
							//printf("edge %d v0 %d v1 %d tan:%d\n",tmpEp->elem,mesh->edge[tmpEp->elem].vert[0],mesh->edge[tmpEp->elem].vert[1],mesh->edge[tmpEp->elem].tan);
							if (mesh->face[tmpFp->elem].edge[i] == tmpEp->elem || mesh->edge[mesh->face[tmpFp->elem].edge[i]].tan == 1) {
								v1 = 1; break;
							}
							tmpEp = tmpEp->next;
						}
						if(v1==1) break;
					}

					if (!v1) {
						/* si sceglie la face giusta, evitando quella attiva */
						if ( mesh->edge[mesh->face[tmpFp->elem].edge[i]].neigh[0] == tmpFp->elem )
							v2 = mesh->edge[mesh->face[tmpFp->elem].edge[i]].neigh[1];
						else v2 = mesh->edge[mesh->face[tmpFp->elem].edge[i]].neigh[0];

						/* infine si controlla di non averla già inserita nella lista per la polyline corrente*/
						v1 = 0;
						tmpFpS = faceP;
						while (tmpFpS) {
							if (v2 == 0 || tmpFpS->elem == v2) { v1 = 1; break; }
							tmpFpS = tmpFpS->next;
						}

						/* se è possibile viene inserita */
						if (!v1) {
							tmpFpI->next = (struct queue*) malloc(sizeof(struct queue));
							if (!tmpFpI->next) ErrorMessage();
							tmpFpI = tmpFpI->next;
							tmpFpI->elem = v2;
							tmpFpI->next = NULL;
	#if DEBUG_GLUE
							printf("%d ",v2);
	#endif
						}
					}
				}
				tmpFp = tmpFp->next;
			}
			fP[n]=faceP;
			n++;
		}
		else
			n++;
	}

#if DEBUG_GLUE
	for(z=0;z<k;z++){
		if(profiles[z]!=NULL){
			tmpFp = fP[z];
			printf("\nFace of Patch %d: ",z);
			while (tmpFp){
				printf("%d ",tmpFp->elem);
				tmpFp = tmpFp->next;
			}
			printf("\n");
		}
	}
#endif

	/* Determinate le face di un Patch, si rimappano i vertici seguendo le
	informazioni della coda delle face.
	L'array è formato da due colonne, la prima indica a quale Patch
	fa riferimento il vertice, la seconda indica quale indice assumerà
	il vertice nel nuovo Patch .... */

	vertex = (int**) malloc((mesh->nVert + 1) * sizeof(int));
	if (!vertex) ErrorMessage();
	for (i=0; i<= mesh->nVert; i++) {
		vertex[i] = (int *) calloc(2, sizeof(int));
		if (!vertex[i]) ErrorMessage();
	}

	// Per ogni profilo
	n=0;
	while(n<k){
		if(profiles[n]!=NULL){
			i = 1;    /* indice per la rimappatura dei vertici e contatore degli stessi */
			v1 = 0;   /* contatore face */
			tmpFp = fP[n];
			while (tmpFp) {
				v1++;
				/* si analizzano tutti i vertici di tutte le face in coda */
				for (j=0; j < mesh->face[tmpFp->elem].nVert; j++) {
					/* vertice da rimappare non ancora rimappato */
					if (!(vertex[mesh->face[tmpFp->elem].vert[j]])[0]) {
						(vertex[mesh->face[tmpFp->elem].vert[j]])[0] = n+1; //patch da 1 a k
						(vertex[mesh->face[tmpFp->elem].vert[j]])[1] = i;
						i++;
					}
				}
				tmpFp = tmpFp->next;
			}
			i -= 1; /* questo è il numero di vertici del patch */

			/* Ora è possibile salvare il Patch */
			tmpM = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
			if (!tmpM) ErrorMessage();
			(*nM).push_back(tmpM);
			(*nM)[n]->nVert = i;
			(*nM)[n]->nFace = v1;
			(*nM)[n]->vert = (Vertex*) malloc(((*nM)[n]->nVert + 1) * sizeof(Vertex));
			if (!(*nM)[n]->vert) ErrorMessage();
			(*nM)[n]->face = (Face*) malloc(((*nM)[n]->nFace + 1) * sizeof(Face));
			if (!(*nM)[n]->face) ErrorMessage();

			/* ... copia dei vertici del Patch ... */
			for (j=1; j <= mesh->nVert; j++) {
				/* è un vertice di questo Patch */
				if ((vertex[j])[0]==n+1) {
					(*nM)[n]->vert[(vertex[j])[1]].x = mesh->vert[j].x;
					(*nM)[n]->vert[(vertex[j])[1]].y = mesh->vert[j].y;
					(*nM)[n]->vert[(vertex[j])[1]].z = mesh->vert[j].z;
					(*nM)[n]->vert[(vertex[j])[1]].tan = mesh->vert[j].tan;
				}
			}

	#if DEBUG_GLUE
			for (j=1; j <= (*nM)[n]->nVert; j++) {
				if (j==1) printf("Nuova lista vertici:\n");
				printf("v %f %f %f tan %d\n",(*nM)[n]->vert[j].x, (*nM)[n]->vert[j].y, (*nM)[n]->vert[j].z,(*nM)[n]->vert[j].tan);
			}
	#endif

			/* ... copia delle faccette del Patch. */
			tmpFp = fP[n];
			i = 1;
			while (tmpFp) {
				(*nM)[n]->face[i].nVert = mesh->face[tmpFp->elem].nVert;

	#if DEBUG_GLUE
				if (i==1) printf("Nuova lista facce:\n");
				printf("Face no.%d  NVertices %d  Vertices ", i, (*nM)[n]->face[i].nVert);
	#endif

				for (j=0; j < mesh->face[tmpFp->elem].nVert; j++) {
					(*nM)[n]->face[i].vert[j] = (vertex[mesh->face[tmpFp->elem].vert[j]])[1];

	#if DEBUG_GLUE
					printf("%d ",(*nM)[n]->face[i].vert[j]);
	#endif
				}
	#if DEBUG_GLUE
				printf("\n");
	#endif

				i++;
				tmpFp = tmpFp->next;
			}
			n++;
		}
		else
			n++;
	}

	/* ... devo recuperare l'ultimo patch, si utilizzano le informazioni della mesh escludendo quelle
	     dei Patch già recuperati. */
	v1 = 0;  /* contatore face del Patch */
	tmpFpI = tmpFpS = NULL;
	for (i=1; i <= mesh->nFace; i++) {
		/* si controlla che la face non faccia parte dei Patch precedenti e che non sia tangente */
		v2 = 0;
		for(z=0;z<k;z++){
			tmpFp = fP[z];
			while (tmpFp) {
				if (tmpFp->elem == i) {
					v2 = 1;
					break;
				}
				tmpFp = tmpFp->next;
			}
		}
		if(v2==0 && mesh->face[i].tan == 1) v2 = 1;

		if (!v2) {
			v1++;
			if (!tmpFpI) {
				tmpFpI = (struct queue*) malloc(sizeof(struct queue));
				if (!tmpFpI) ErrorMessage();
				tmpFpS = tmpFpI;
			} else {
				tmpFpS->next = (struct queue*) malloc(sizeof(struct queue));
				if (!tmpFpS->next) ErrorMessage();
				tmpFpS = tmpFpS->next;
			}
			tmpFpS->elem = i;
			tmpFpS->next = NULL;
		}
	}

#if DEBUG_GLUE
	tmpFp = tmpFpI;
	printf("Face of last Patch: ");
	while (tmpFp) { printf("%d ",tmpFp->elem); tmpFp = tmpFp->next; }
	printf("\n");
#endif

	/* Rimappatura vertici del Patch */
	for (i = 0; i <= mesh->nVert; i++) { (vertex[i])[0] = (vertex[i])[1] = 0; }
	i = 1;    /* indice e contatore dei vertici */
	tmpFp = tmpFpI;
	while (tmpFp) {
		/* si analizzano tutti i vertici di tutte le face in coda */
		for (j=0; j < mesh->face[tmpFp->elem].nVert; j++) {
			/* vertice da rimappare non ancora rimappato */
			if (!(vertex[mesh->face[tmpFp->elem].vert[j]])[0]) {

				(vertex[mesh->face[tmpFp->elem].vert[j]])[0] = 1;
				(vertex[mesh->face[tmpFp->elem].vert[j]])[1] = i;
				i++;
			}
		}
		tmpFp = tmpFp->next;
	}
	i -= 1; /* questo è il numero di vertici del parch */

	/* Ora è possibile salvare anche l'ultimo Patch */
	NmF = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
	if (!NmF) ErrorMessage();
	NmF->nVert = i;
	NmF->nFace = v1;
	NmF->vert = (Vertex*) malloc((NmF->nVert + 1) * sizeof(Vertex));
	if (!NmF->vert) ErrorMessage();
	NmF->face = (Face*) malloc((NmF->nFace + 1) * sizeof(Face));
	if (!NmF->face) ErrorMessage();

	/* ... copia dei vertici del secondo Patch ... */
	for (j=1; j <= mesh->nVert; j++) {

		/* è un vertice di questo Patch */
		if ((vertex[j])[0]) {
			NmF->vert[(vertex[j])[1]].x = mesh->vert[j].x;
			NmF->vert[(vertex[j])[1]].y = mesh->vert[j].y;
			NmF->vert[(vertex[j])[1]].z = mesh->vert[j].z;
			NmF->vert[(vertex[j])[1]].tan = mesh->vert[j].tan;
		}
	}

#if DEBUG_GLUE
	for (j=1; j <= NmF->nVert; j++) {
		if (j==1) printf("Nuova lista vertici:\n");
		printf("v %f %f %f tan %d\n",NmF->vert[j].x, NmF->vert[j].y, NmF->vert[j].z,NmF->vert[j].tan);
	}
#endif

	/* ... copia delle faccette del primo Patch. */
	tmpFp = tmpFpI;
	i = 1;
	while (tmpFp) {

		NmF->face[i].nVert = mesh->face[tmpFp->elem].nVert;

#if DEBUG_GLUE
		if (i==1) printf("Nuova lista facce:\n");
		printf("Face no.%d  NVertices %d  Vertices ", i, NmF->face[i].nVert);
#endif

		for (j=0; j < mesh->face[tmpFp->elem].nVert; j++) {

			NmF->face[i].vert[j] = (vertex[mesh->face[tmpFp->elem].vert[j]])[1];
#if DEBUG_GLUE
			printf("%d ",NmF->face[i].vert[j]);
#endif
		}
#if DEBUG_GLUE
		printf("\n");
#endif

		i++;
		tmpFp = tmpFp->next;
	}


	/* Free Memory */
	for(z=0;z<k;z++){
		while (eP[z]) {
			tmpEp = eP[z];
			eP[z] = eP[z]->next;
			free(tmpEp);
		}
	}

	tmpFp = tmpFpI;
	while (tmpFp) {
		tmpFpS = tmpFp;
		tmpFp = tmpFp->next;
		free(tmpFpS);
	}

	for(z=0;z<k;z++){
		tmpFp = fP[z];
		while (tmpFp) {
			tmpFpS = tmpFp;
			tmpFp = tmpFp->next;
			free(tmpFpS);
		}
	}

	for (i=0; i <= mesh->nVert; i++) {
		free(vertex[i]);
	}
	free(vertex);
	// TODO
/* BUG: dopo lo split su mesh1 si perdono le informazioni su mesh2
	free(mesh->vert);  free(mesh->edge);
	free(mesh->face);  free(mesh);
*/

	for(z=0;z<k;z++){
		if(profiles[z]!=NULL)
			(*nM)[z]->mod_LoadSubdivMesh();
	}
	NmF->mod_LoadSubdivMesh();

#if DEBUG_GLUE
	printf("<<----------------------------SPLIT M\n");
#endif

	return NmF;

}

/* Funzione per la ricerca dei vertici vicini tra due mesh distinte:
   l'array delle coppie create viene dimensionato sul numero di vertici
   minore tra le due mesh e comunque sul numero di vertici della mesh 2. */
int* gen_searchVneighbour(Mod_SubdivMesh *mesh_1, Mod_SubdivMesh *mesh_2, float toll) {

	int *vneigh;       /* array dinamico delle coppie di vertici coincidenti */
	int i, j, mnv, Mnv;
	Mod_SubdivMesh *mnvMesh, *MnvMesh;
	char m, M;

	/* ottimizzazione sul numero minore di vertici */
	if ( mesh_2->nVert <= mesh_1->nVert ) {
		mnv = mesh_2->nVert;  mnvMesh = mesh_2;
		Mnv = mesh_1->nVert;  MnvMesh = mesh_1;
		m = '2';  M = '1';
	} else {
		mnv = mesh_1->nVert;  mnvMesh = mesh_1;
		Mnv = mesh_2->nVert;  MnvMesh = mesh_2;
		m = '1';  M = '2';
	}

	vneigh = (int*)calloc((mnv + 1), sizeof(int)); /* l'indice 0 rimane inutilizzato */
	if (!vneigh) ErrorMessage();

#if DEBUG_GLUE
	printf("SEARCH_1---------------------------->>\n");
#endif

	/* ottimizzazione della ricerca: m * M potrebbe essere migliore di M * m */
	for (i=1; i <= mnvMesh->nVert; i++) {
		if (mnvMesh->vert[i].bound /*|| mnvMesh->vert[i].tan==1*/) {
			for (j=1; j <= MnvMesh->nVert; j++) {
				if ((MnvMesh->vert[j].bound /*|| MnvMesh->vert[j].tan==1*/)&&
						fabs(mnvMesh->vert[i].x - MnvMesh->vert[j].x) < toll &&
						fabs(mnvMesh->vert[i].y - MnvMesh->vert[j].y) < toll &&
						fabs(mnvMesh->vert[i].z - MnvMesh->vert[j].z) < toll) {
#if DEBUG_GLUE
					printf("Find: vertex mesh %c neighbour vertex mesh %c (%d,%d)\n",
							m,M,i,j);
#endif
					vneigh[i] = j;
				}
			}
		}
	}

	Mnv = 0;
	for (i=1; i <= mnv; i++)
		if (!vneigh[i]) Mnv++;
	if (mnv == Mnv) {
#if DEBUG_GLUE
		printf("Not Found neighbour vertex!\n");
		printf("<<----------------------------SEARCH_1\n");
#endif
		return NULL;
	}

#if DEBUG_GLUE
	printf("<<----------------------------SEARCH_1\n");
#endif

	return vneigh;
}

/* Funzione della coerenza delle normali tra due mesh unite
   TRUE = coerenza. */
bool gen_normalCheckDouble(Mod_SubdivMesh *mesh_1,Mod_SubdivMesh *mesh_2, int *vneigh) {

	int i;
	indices vem1, vem2;  /* indici ordinati dei vertici,
                          di uno degli edge di unione */
	bool check;

#if DEBUG_GLUE
	printf("NORMAL CHECK---------------------------->>\n");
#endif

	/* Individuazione di un edge di unione */
	if (mesh_2->nEdge <= mesh_1->nEdge) {

		/* per gli edge di bordo il secondo campo di neigh è 0 */
		for (i=1; i <= mesh_2->nEdge; i++) {
			if (!mesh_2->edge[i].neigh[1]) {

				if (mesh_2->nVert <= mesh_1->nVert) {
					if ( vneigh[mesh_2->edge[i].vert[0]] &&
							vneigh[mesh_2->edge[i].vert[1]]) { /* edge di unione */
#if DEBUG_GLUE
						printf("Find: edge mesh 1 %d--%d stick edge mesh 2 %d--%d\n",
								vneigh[mesh_2->edge[i].vert[0]],
								vneigh[mesh_2->edge[i].vert[1]],
								mesh_2->edge[i].vert[0],mesh_2->edge[i].vert[1]);
#endif
						vem1[0] = vneigh[mesh_2->edge[i].vert[0]];
						vem1[1] = vneigh[mesh_2->edge[i].vert[1]];
						vem2[0] = mesh_2->edge[i].vert[0];
						vem2[1] = mesh_2->edge[i].vert[1];
						break;
					}

				} else {

					if ( vneigh[mesh_1->edge[i].vert[0]] &&
							vneigh[mesh_1->edge[i].vert[1]]) { /* edge di unione */
#if DEBUG_GLUE
						printf("Find: edge mesh 1 %d--%d stick edge mesh 2 %d--%d\n",
								mesh_1->edge[i].vert[0],mesh_1->edge[i].vert[1],
								vneigh[mesh_1->edge[i].vert[0]],
								vneigh[mesh_1->edge[i].vert[1]]);
#endif
						vem1[0] = mesh_1->edge[i].vert[0];
						vem1[1] = mesh_1->edge[i].vert[1];
						vem2[0] = vneigh[mesh_1->edge[i].vert[0]];
						vem2[1] = vneigh[mesh_1->edge[i].vert[1]];
						break;
					}
				}
			}
		}

	} else {

		/* per gli edge di bordo il secondo campo di neigh è 0 */
		for (i=1; i <= mesh_1->nEdge; i++) {
			if (!mesh_1->edge[i].neigh[1]) { /* edge di bordo */

				if (mesh_2->nVert <= mesh_1->nVert) {
					if ( vneigh[mesh_2->edge[i].vert[0]] &&
							vneigh[mesh_2->edge[i].vert[1]]) { /* edge di unione */
#if DEBUG_GLUE
						printf("Find: edge mesh 1 %d--%d stick edge mesh 2 %d--%d\n",
								vneigh[mesh_2->edge[i].vert[0]],
								vneigh[mesh_2->edge[i].vert[1]],
								mesh_2->edge[i].vert[0],mesh_2->edge[i].vert[1]);
#endif
						vem1[0] = vneigh[mesh_2->edge[i].vert[0]];
						vem1[1] = vneigh[mesh_2->edge[i].vert[1]];
						vem2[0] = mesh_2->edge[i].vert[0];
						vem2[1] = mesh_2->edge[i].vert[1];
						break;
					}

				} else {

					if ( vneigh[mesh_1->edge[i].vert[0]] &&
							vneigh[mesh_1->edge[i].vert[1]]) { /* edge di unione */
#if DEBUG_GLUE
						printf("Find: edge mesh 1 %d--%d stick edge mesh 2 %d--%d\n",
								mesh_1->edge[i].vert[0],mesh_1->edge[i].vert[1],
								vneigh[mesh_1->edge[i].vert[0]],
								vneigh[mesh_1->edge[i].vert[1]]);
#endif
						vem1[0] = mesh_1->edge[i].vert[0];
						vem1[1] = mesh_1->edge[i].vert[1];
						vem2[0] = vneigh[mesh_1->edge[i].vert[0]];
						vem2[1] = vneigh[mesh_1->edge[i].vert[1]];
						break;
					}
				}
			}
		}
	}

	/* ricerca degli indici ordinati dell'edge */
	if (mesh_2->nVert <= mesh_1->nVert) {
		for (i=1; i <= mesh_1->nEdge; i++) {

			if ( (vem1[0] == mesh_1->edge[i].vert[0] &&
					vem1[1] == mesh_1->edge[i].vert[1]) ||
					(vem1[0] == mesh_1->edge[i].vert[1] &&
							vem1[1] == mesh_1->edge[i].vert[0])) {
				vem1[0] = mesh_1->edge[i].vert[0];
				vem1[1] = mesh_1->edge[i].vert[1];
			}
		}

	} else {
		for (i=1; i <= mesh_2->nEdge; i++) {

			if ( (vem2[0] == mesh_2->edge[i].vert[0] &&
					vem2[1] == mesh_2->edge[i].vert[1]) ||
					(vem2[0] == mesh_2->edge[i].vert[1] &&
							vem2[1] == mesh_2->edge[i].vert[0])) {
				vem2[0] = mesh_2->edge[i].vert[0];
				vem2[1] = mesh_2->edge[i].vert[1];
			}
		}
	}

	/* Test di percorrenza dell'edge: se due faccette adiacenti, che quindi
     verranno unite, percorrono lo stesso edge nelle due direzioni opposte,
     allora le normali per le due mesh sono coerenti. */
	if (mesh_2->nVert <= mesh_1->nVert) {

		if (vneigh[vem2[1]] == vem1[0] && vneigh[vem2[1]] == vem1[0] ) check = true;
		else check = false;

	} else {

		if (vneigh[vem1[1]] == vem2[0] && vneigh[vem1[1]] == vem2[0] ) check = true;
		else check = false;

	}

#if DEBUG_GLUE
	if (check) printf("Normal OK!\n");
	else printf("Call reverse normal!!\n");
	printf("<<----------------------------NORMAL CHECK\n");
#endif

	return check;
}

/* Procedura per invertire l'orientamento delle normali relative alle facce. */
void gen_reverseNormal(Mod_SubdivMesh *mesh) {

	int i, j;
	int *temp;

#if DEBUG_GLUE
	printf("REVERSE NORMAL---------------------------->>\n");
#endif

	for (i=1; i <= mesh->nFace; i++) {

		temp = (int*)calloc(mesh->face[i].nVert, sizeof(int));
		if (!temp) ErrorMessage();

#if DEBUG_GLUE
		printf("Face no.%d  NVertices %d  Vertices ",i,mesh->face[i].nVert);
#endif

		for (j=0; j < mesh->face[i].nVert; j++) { /* memorizza l'ordine attuale */
#if DEBUG_GLUE
			printf("%d ",mesh->face[i].vert[j]);
#endif
			temp[j] = mesh->face[i].vert[j];
		}

#if DEBUG_GLUE
		printf("turn ");
#endif

		for (j=0; j < mesh->face[i].nVert; j++) { /* inversione dell'ordine */
#if DEBUG_GLUE
			printf("%d ",temp[(mesh->face[i].nVert -1 - j)]);
#endif
			mesh->face[i].vert[j] = temp[(mesh->face[i].nVert -1 - j)];
		}

		free(temp);
#if DEBUG_GLUE
		printf("\n");
#endif

	}

#if DEBUG_GLUE
	printf("<<----------------------------REVERSE NORMAL\n");
#endif

	mesh->mod_LoadSubdivMesh();

	return;
}

/* Procedura utilizzata per l'unione effettiva di due mesh. */
Mod_SubdivMesh* gen_glueCoupleMesh(Mod_SubdivMesh *mesh_1, Mod_SubdivMesh *mesh_2, int **vneigh) {

	int i, j, mnv, Mnv;
	Mod_SubdivMesh *mnvMesh, *MnvMesh;
	Mod_SubdivMesh *new_mesh;

	/* mesh con cardinalità minore di vertici */
	if ( mesh_2->nVert <= mesh_1->nVert ) {
		mnv = mesh_2->nVert;  Mnv = mesh_1->nVert;
		mnvMesh = mesh_2;  MnvMesh = mesh_1;
	} else {
		mnv = mesh_1->nVert;  Mnv = mesh_2->nVert;
		mnvMesh = mesh_1;  MnvMesh = mesh_2;
	}

	/* vertici che non saranno rimappati */
	j = 0;
	for (i=1; i <= mnv; i++) {
		if (!(*vneigh)[i]) j++;
	}

#if DEBUG_GLUE
	printf("GLUE---------------------------->>\n");
#endif

	/* Creazione della mesh unione delle due */
	new_mesh = (Mod_SubdivMesh*) malloc(sizeof(Mod_SubdivMesh));
	if (!new_mesh) ErrorMessage();
	new_mesh->nVert = MnvMesh->nVert + j;
	new_mesh->nFace = MnvMesh->nFace + mnvMesh->nFace;
	new_mesh->vert  = (Vertex*) malloc((new_mesh->nVert + 1) * sizeof(Vertex));
	if (!new_mesh->vert) ErrorMessage();
	new_mesh->face = (Face*) malloc((new_mesh->nFace + 1) * sizeof(Face));
	if (!new_mesh->face) ErrorMessage();

	/* ... copia dei vertici delle due mesh e ... */
	for (i=1; i <= Mnv; i++) {
#if DEBUG_GLUE
		if (i==1) printf("Nuova lista vertici:\n");
#endif
		new_mesh->vert[i].x = MnvMesh->vert[i].x;
		new_mesh->vert[i].y = MnvMesh->vert[i].y;
		new_mesh->vert[i].z = MnvMesh->vert[i].z;
		new_mesh->vert[i].tan = MnvMesh->vert[i].tan;
#if DEBUG_GLUE
		printf("v %f %f %f tan %d\n",new_mesh->vert[i].x,
				new_mesh->vert[i].y,new_mesh->vert[i].z,new_mesh->vert[i].tan);
#endif
	}

	j = (Mnv + 1);
	for (i=1; i <= mnv; i++) {
		if (!(*vneigh)[i]) {
			new_mesh->vert[j].x = mnvMesh->vert[i].x;
			new_mesh->vert[j].y = mnvMesh->vert[i].y;
			new_mesh->vert[j].z = mnvMesh->vert[i].z;
			new_mesh->vert[j].tan = mnvMesh->vert[i].tan;
			j++;
#if DEBUG_GLUE
			printf("v %f %f %f tan %d\n",new_mesh->vert[j-1].x,new_mesh->vert[j-1].y,new_mesh->vert[j-1].z,new_mesh->vert[j-1].tan);
#endif
		}
	}

	/* ... copia delle faccette delle due mesh. */
	for (i=1; i <= MnvMesh->nFace; i++) {

		new_mesh->face[i].nVert = MnvMesh->face[i].nVert;
#if DEBUG_GLUE
		if (i==1) printf("Nuova lista facce:\n");
		printf("Face no.%d  NVertices %d  Vertices ",i,new_mesh->face[i].nVert);
#endif

		for (j=0; j < MnvMesh->face[i].nVert; j++) {
			new_mesh->face[i].vert[j] = MnvMesh->face[i].vert[j];
#if DEBUG_GLUE
			printf("%d ",new_mesh->face[i].vert[j]);
#endif
		}
#if DEBUG_GLUE
		printf("\n");
#endif
	}

	j = Mnv + 1;
	for (i=1; i <= mnv; i++) { /* rimappatura indici dei vertici altra mesh */
		if (!(*vneigh)[i]) (*vneigh)[i] = j++;
	}

	for (i=(MnvMesh->nFace + 1); i <= (MnvMesh->nFace + mnvMesh->nFace); i++) {

		new_mesh->face[i].nVert = mnvMesh->face[(i-MnvMesh->nFace)].nVert;
#if DEBUG_GLUE
		printf("Face no.%d  NVertices %d  Vertices ",i,new_mesh->face[i].nVert);
#endif

		for (j=0; j < mnvMesh->face[(i-MnvMesh->nFace)].nVert; j++) {
			new_mesh->face[i].vert[j] = (*vneigh)[mnvMesh->face[(i-MnvMesh->nFace)].vert[j]];
#if DEBUG_GLUE
			printf("%d ",new_mesh->face[i].vert[j]);
#endif
		}
#if DEBUG_GLUE
		printf("\n");
#endif
	}

#if DEBUG_GLUE
	printf("<<----------------------------GLUE\n");
#endif

	free(*vneigh);  *vneigh = NULL;

	new_mesh->mod_LoadSubdivMesh();

	return new_mesh;
}

/* Funzione per inglobare un insieme di mesh in un unica mesh */
Mod_SubdivMesh* gen_meshAdd(vector<Mod_SubdivMesh*> *nM, int m){


	int i,j,h,k,nvAcc;
	Mod_SubdivMesh *res;

	res = (Mod_SubdivMesh*)malloc(sizeof(Mod_SubdivMesh));
	if (!res) ErrorMessage();
	res->nVert = 0;
	res->nFace = 0;
	// calcolo numero totale di vert, edge, face
	for(i=0;i<m;i++){
		res->nVert = res->nVert + (*nM)[i]->nVert;
		res->nFace = res->nFace + (*nM)[i]->nFace;
	}
	// copio i vertici
	h=1;
	res->vert = (Vertex*)malloc((res->nVert+1)*sizeof(Vertex));
	if (!res->vert) ErrorMessage();
	for(i=0;i<m;i++){
		for(j=1;j<=(*nM)[i]->nVert;j++){
			res->vert[h].x=(*nM)[i]->vert[j].x;
			res->vert[h].y=(*nM)[i]->vert[j].y;
			res->vert[h].z=(*nM)[i]->vert[j].z;
			h++;
		}
	}
	//copio le face
	h=1;
	res->face = (Face*)malloc((res->nFace+1)*sizeof(Face));
	if (!res->face) ErrorMessage();
	nvAcc=0;
	for(i=0;i<m;i++){
		if(i!=0) nvAcc=nvAcc+(*nM)[i-1]->nVert;
		for(j=1;j<=(*nM)[i]->nFace;j++){
			res->face[h].nVert=(*nM)[i]->face[j].nVert;
			for(k=0;k<((*nM)[i]->face[j].nVert);k++){
				res->face[h].vert[k]=(*nM)[i]->face[j].vert[k]+nvAcc;
			}
			h++;
		}
	}
	res->mod_LoadSubdivMesh();

	return res;
}

// Apply boolean operators on two meshes
vector<Mod_SubdivMesh*> gen_applyBooleanOps(Mod_SubdivMesh *mesh_1, Mod_SubdivMesh *mesh_2) {

	int i,z,h,m,t,np,nTan1,nTan2;
	Mod_SubdivMesh* mesh_g[4];       /* struttura dati unstructured mesh */
	Mod_SubdivMesh *tmpM;
	Mod_SubdivMesh *mesh_a, *mesh_b;
	vector<Mod_SubdivMesh*> result;
	float tollerance = TOLL;          /* tolleranza per il test di vicinanza */
	int  *vneigh;         /* array dinamico delle coppie di vertici coincidenti */
	q_point *EdgeMesh1_FaceMesh2,     /* lista intersezioni Edge-Face */
	*EdgeMesh2_FaceMesh1,
	*Qtmp;
	i_point *tmp;
	Vertex *bb1,*bb2;

	vneigh = NULL;

	for(int y=0;y<4;y++)
		mesh_g[y]=NULL;


	/* Controllo vincolo TWO-MANIFOLD */
	if (!gen_TwoManifold(mesh_1)) {
		printf("mesh_1: Two-Manifold Condition test failed\n");
		exit(1);
	}
	if (mesh_2 && !gen_TwoManifold(mesh_2)) {
		printf("mesh_2: Two-Manifold Condition test failed\n");
		exit(1);
	}

	bb1 = gen_computeBoundingBox(&(_mesh[0]));
	bb2 = gen_computeBoundingBox(&(_mesh[1]));
	// Test preliminare di intersezione
	if(!gen_checkBoxCollision(bb1,bb2)){
		cout << "Le due mesh non si intersecano" << endl;
		return result;
	}

	// marco le facce appartenenti al bb di intersezione
	for(int u=1;u<mesh_1->nFace;u++){
		if(gen_faceInBox(mesh_1,u,bb2))
			mesh_1->face[u].bb = 1;
		else
			mesh_1->face[u].bb = 0;
	}
	for(int u=1;u<mesh_2->nFace;u++){
		if(gen_faceInBox(mesh_2,u,bb1))
			mesh_2->face[u].bb = 1;
		else
			mesh_2->face[u].bb = 0;
	}

	nTan1 = mesh_1->nVert;
	nTan2 = mesh_2->nVert;
	/* Test di tangenza facce */
	gen_fTg(&mesh_1,&mesh_2);
	// numero nuovi vertici tangenti
	nTan1 = mesh_1->nVert-nTan1;
	nTan2 = mesh_2->nVert-nTan2;

	string filepath1 = mesh_1->filepath;
	string filepath2 = mesh_2->filepath;
	mesh_1->mod_save("mesh1afterTan",filepath1);
	mesh_2->mod_save("mesh2afterTan",filepath1);

	/* Si individuano gli edge della mesh 1 che intersecano face della mesh 2
         e viceversa. */
	EdgeMesh1_FaceMesh2 = gen_edgeIntersectFace(mesh_1, mesh_2);
	EdgeMesh2_FaceMesh1 = gen_edgeIntersectFace(mesh_2, mesh_1);


	if (!EdgeMesh1_FaceMesh2 && !EdgeMesh2_FaceMesh1) { /* le mesh non
                                                              si intersecano */
		printf("Mesh 1 doesn't intersect mesh 2 ... OUT!\n");
		fflush(stdout);
		return result;
	} else if (!EdgeMesh1_FaceMesh2) { /* la mesh 2 interseca in un
                                            unica face la mesh 1 */

		while (!EdgeMesh1_FaceMesh2) {

			i = EdgeMesh2_FaceMesh1->indexFace;
#if DEBUG_GLUE
			printf("All intersection into face %d mesh 1\n",i);
#endif

			if (mesh_1->face[i].nVert == 3) gen_splitTriangleFace(mesh_1, i);
			else gen_triangulationOneFace(mesh_1, i);

			do {
				Qtmp = EdgeMesh2_FaceMesh1;
				EdgeMesh2_FaceMesh1 = EdgeMesh2_FaceMesh1->next;
				free(Qtmp);
			} while(EdgeMesh2_FaceMesh1);

			EdgeMesh1_FaceMesh2 = gen_edgeIntersectFace(mesh_1, mesh_2);
			EdgeMesh2_FaceMesh1 = gen_edgeIntersectFace(mesh_2, mesh_1);

		}

	} else if (!EdgeMesh2_FaceMesh1) { /* la mesh 1 interseca in un
                                            unica face la mesh 2 */

		while (!EdgeMesh2_FaceMesh1) {

			i = EdgeMesh1_FaceMesh2->indexFace;
#if DEBUG_GLUE
			printf("All intersection into face %d mesh 2\n",i);
#endif
			if (mesh_2->face[i].nVert == 3) gen_splitTriangleFace(mesh_2, i);
			else gen_triangulationOneFace(mesh_2, i);

			do {
				Qtmp = EdgeMesh1_FaceMesh2;
				EdgeMesh1_FaceMesh2 = EdgeMesh1_FaceMesh2->next;
				free(Qtmp);
			} while(EdgeMesh1_FaceMesh2);

			EdgeMesh1_FaceMesh2 = gen_edgeIntersectFace(mesh_1, mesh_2);
			EdgeMesh2_FaceMesh1 = gen_edgeIntersectFace(mesh_2, mesh_1);

		}

	}

	/* Marco tutti i punti di intersezione interessati dalla tangenza */
	q_point* temp;
	temp = EdgeMesh1_FaceMesh2;
	while(temp!=NULL){
		z = -1;
		z = mesh_1->mod_find_in_vert(temp->v);
		if(z!=-1){
			temp->tan = mesh_1->vert[z].tan;
			temp->ins = mesh_1->vert[z].ins;
		}
		else{
			temp->tan = 0;
			temp->ins = 0;
		}
		temp = temp->next;
	}
	temp = EdgeMesh2_FaceMesh1;
	while(temp!=NULL){
		z = -1;
		z = mesh_2->mod_find_in_vert(temp->v);
		if(z!=-1){
			temp->tan = mesh_2->vert[z].tan;
			temp->ins = mesh_2->vert[z].ins;
		}
		else{
			temp->tan = 0;
			temp->ins = 0;
		}
		temp = temp->next;
	}
/*
	printf("DEBUG PUNTATORI\n");
	temp = EdgeMesh1_FaceMesh2;
	while(temp){
		printf("temp: %g %g %g tan:%d ins:%d\n",temp->v.x,temp->v.y,temp->v.z,temp->tan,temp->ins);
		temp = temp->next;
	}
	printf("\n");
	temp = EdgeMesh2_FaceMesh1;
	while(temp){
		printf("temp: %g %g %g tan:%d ins:%d\n",temp->v.x,temp->v.y,temp->v.z,temp->tan,temp->ins);
		temp = temp->next;
	}
	printf("exit\n");
	exit(1);
*/
	/*
    MORENO
    Dopo aver calcolato tutte le intersezioni tra le due mesh:
    - applico una prima volta l'algoritmo, eliminando dalla lista i punti inseriti nella polyline
    - ripeto fino a quando la lista non è vuota
    Uso un array di puntatory a qpoint per salvare i diversi profili di intersezione
	 */
	i_point** profiles;
	i_point** tmpProfiles;
	vector<int> isolatedTan;
	int k = 0;
	//Creo una copia di lavoro delle liste di intersezioni,da queste liste toglierò i punti man mano che li uso
	q_point *E1_F2, *E2_F1, *tmpEF, *tmpEMFM;

	tmpEMFM = EdgeMesh1_FaceMesh2;
	E1_F2=(q_point*)malloc(sizeof(q_point));
	if (!E1_F2) ErrorMessage();
	tmpEF=E1_F2;
	do{
		tmpEF->indexEdge=tmpEMFM->indexEdge;
		tmpEF->indexFace=tmpEMFM->indexFace;
		tmpEF->tan=tmpEMFM->tan;
		tmpEF->ins=tmpEMFM->ins;
		tmpEF->v.x=tmpEMFM->v.x;
		tmpEF->v.y=tmpEMFM->v.y;
		tmpEF->v.z=tmpEMFM->v.z;
		if(tmpEMFM->next!=NULL){
			tmpEF->next=(q_point*)malloc(sizeof(q_point));
			tmpEF=tmpEF->next;
		}
		else
			tmpEF->next=NULL;
		tmpEMFM=tmpEMFM->next;
	}while(tmpEMFM!=NULL);

	tmpEMFM = EdgeMesh2_FaceMesh1;
	E2_F1=(q_point*)malloc(sizeof(q_point));
	if (!E2_F1) ErrorMessage();
	tmpEF=E2_F1;
	do{
		tmpEF->indexEdge=tmpEMFM->indexEdge;
		tmpEF->indexFace=tmpEMFM->indexFace;
		tmpEF->tan=tmpEMFM->tan;
		tmpEF->ins=tmpEMFM->ins;
		tmpEF->v.x=tmpEMFM->v.x;
		tmpEF->v.y=tmpEMFM->v.y;
		tmpEF->v.z=tmpEMFM->v.z;
		if(tmpEMFM->next!=NULL){
			tmpEF->next=(q_point*)malloc(sizeof(q_point));
			tmpEF=tmpEF->next;
		}
		else
			tmpEF->next=NULL;
		tmpEMFM=tmpEMFM->next;
	}while(tmpEMFM!=NULL);

	//determino i profili di intersezione
	k++;
	tmpProfiles = NULL;

	//calcolo punti di intersezione distinti
	int *count,*countTmp;    // per contare il numero di intersezioni di ciascun profilo
	int acc,acc1,nInt,nIntTmp,num;
	i_point* intList = NULL;
	nInt=gen_countIntersections(mesh_1, mesh_2, E1_F2, E2_F1,intList);
	nIntTmp=nInt;
	count = NULL;
	countTmp = NULL;
	acc = 0;
	num = 0;
	//La lista delle intersezioni distinte non viene usata,si usa solo il contatore
	//devo triangolarizzare le facce che hanno un intero profilo al loro interno
	vector <int> faceSplit(MAXVAL);
	vector <int> queueM(MAXVAL);
	for(z=0;z<MAXVAL;z++){
		faceSplit[z]=-1;
		queueM[z]=-1;
	}

	while(nIntTmp!=0){
		profiles = (i_point**) malloc(k * sizeof(i_point));
		if (!profiles) ErrorMessage();
		count = (int*) malloc(k * sizeof(int));
		if (!count) ErrorMessage();
		for (z=0; z<(k-1); z++) {
			profiles[z] = tmpProfiles[z];
			count[z]=countTmp[z];
		}
		profiles[k-1] = gen_buildPolygonProfile(mesh_1, &E1_F2, mesh_2, &E2_F1, &nIntTmp, &num, &faceSplit, &queueM, &np, nTan1, nTan2);
		isolatedTan.push_back(np);
		if(tmpProfiles) free(tmpProfiles);
		tmpProfiles = profiles;
		if(k == 1)
			count[k-1] = num; //nInt - nIntTmp;
		else
			count[k-1] = num; //nInt - acc - nIntTmp;
		if(countTmp) free(countTmp);
		countTmp = count;
		acc = acc + count[k-1];
		k++;
	}
	/* vedo se è necessario triangolarizzare facce e ricalcolare i profili */ // Nota: necessaria una funzione di triangolarizzazione smart
	for(z=0;z<(k-1);z++){
		if(!profiles[k-1] && isolatedTan[k-1]==0){
			//triangolarizzazione facce
			int d,p;
			for(d=0;d<MAXVAL;d++){
				if(faceSplit[d]==-1)
					break;
				if(queueM[d] == EM1FM2){
					if (mesh_2->face[faceSplit[d]].nVert == 3)
						gen_splitTriangleFace(mesh_2, faceSplit[d]);
					else
						gen_triangulationOneFace(mesh_2, faceSplit[d]);
					//aggiorno indici facce
					for(p=d;p<MAXVAL;p++){
						if(faceSplit[p]==-1)
							break;
						if(faceSplit[p]>faceSplit[d])
							faceSplit[p]++;
					}
				}
				else if(queueM[d] == EM2FM1){
					if (mesh_1->face[faceSplit[d]].nVert == 3)
						gen_splitTriangleFace(mesh_1, faceSplit[d]);
					else
						gen_triangulationOneFace(mesh_1, faceSplit[d]);
					//aggiorno indici facce
					for(p=d;p<MAXVAL;p++){
						if(faceSplit[p]==-1)
							break;
						if(faceSplit[p]>faceSplit[d])
							faceSplit[p]++;
					}
				}
			}

			//ricalcolo le intersezioni
			do {
				Qtmp = EdgeMesh1_FaceMesh2;
				EdgeMesh1_FaceMesh2 = EdgeMesh1_FaceMesh2->next;
				free(Qtmp);
			} while(EdgeMesh1_FaceMesh2);
			do {
				Qtmp = EdgeMesh2_FaceMesh1;
				EdgeMesh2_FaceMesh1 = EdgeMesh2_FaceMesh1->next;
				free(Qtmp);
			} while(EdgeMesh2_FaceMesh1);

			EdgeMesh1_FaceMesh2 = gen_edgeIntersectFace(mesh_1, mesh_2);
			EdgeMesh2_FaceMesh1 = gen_edgeIntersectFace(mesh_2, mesh_1);

			/* Marco tutti i punti di intersezione interessati dalla tangenza */
			for(int v=1;v<=mesh_1->nVert;v++){
				temp = EdgeMesh1_FaceMesh2;
				while(temp!=NULL){
					if(temp->v.x==mesh_1->vert[v].x && temp->v.y==mesh_1->vert[v].y && temp->v.z==mesh_1->vert[v].z){
						temp->tan = mesh_1->vert[v].tan;
						temp->ins = mesh_1->vert[v].ins;
						break;
					}
					temp = temp->next;
				}
			}
			for(int v=1;v<=mesh_2->nVert;v++){
				temp = EdgeMesh2_FaceMesh1;
				while(temp!=NULL){
					if(temp->v.x==mesh_2->vert[v].x && temp->v.y==mesh_2->vert[v].y && temp->v.z==mesh_2->vert[v].z){
						temp->tan = mesh_2->vert[v].tan;
						temp->ins = mesh_2->vert[v].ins;
						break;
					}
					temp = temp->next;
				}
			}

			//ricreo copie di lavoro, prima libero la memoria
			while(E1_F2){
				tmpEF = E1_F2;
				E1_F2 = E1_F2->next;
				free(tmpEF);
			}
			while(E2_F1){
				tmpEF = E2_F1;
				E2_F1 = E2_F1->next;
				free(tmpEF);
			}
			tmpEMFM = EdgeMesh1_FaceMesh2;
			E1_F2=(q_point*)malloc(sizeof(q_point));
			if (!E1_F2) ErrorMessage();
			tmpEF=E1_F2;
			do{
				tmpEF->indexEdge=tmpEMFM->indexEdge;
				tmpEF->indexFace=tmpEMFM->indexFace;
				tmpEF->tan=tmpEMFM->tan;
				tmpEF->ins=tmpEMFM->ins;
				tmpEF->v.x=tmpEMFM->v.x;
				tmpEF->v.y=tmpEMFM->v.y;
				tmpEF->v.z=tmpEMFM->v.z;
				if(tmpEMFM->next!=NULL){
					tmpEF->next=(q_point*)malloc(sizeof(q_point));
					tmpEF=tmpEF->next;
				}
				else
					tmpEF->next=NULL;
				tmpEMFM=tmpEMFM->next;
			}while(tmpEMFM!=NULL);
			tmpEMFM = EdgeMesh2_FaceMesh1;
			E2_F1=(q_point*)malloc(sizeof(q_point));
			if (!E2_F1) ErrorMessage();
			tmpEF=E2_F1;
			do{
				tmpEF->indexEdge=tmpEMFM->indexEdge;
				tmpEF->indexFace=tmpEMFM->indexFace;
				tmpEF->tan=tmpEMFM->tan;
				tmpEF->ins=tmpEMFM->ins;
				tmpEF->v.x=tmpEMFM->v.x;
				tmpEF->v.y=tmpEMFM->v.y;
				tmpEF->v.z=tmpEMFM->v.z;
				if(tmpEMFM->next!=NULL){
					tmpEF->next=(q_point*)malloc(sizeof(q_point));
					tmpEF=tmpEF->next;
				}
				else
					tmpEF->next=NULL;
				tmpEMFM=tmpEMFM->next;
			}while(tmpEMFM!=NULL);
			//ricalcolo i profili
			nInt=gen_countIntersections(mesh_1, mesh_2, E1_F2, E2_F1,intList);
			nIntTmp=nInt;
			acc = 0;
			for(z=0;z<(k-1);z++){
				profiles[z] = gen_buildPolygonProfile(mesh_1, &E1_F2, mesh_2, &E2_F1, &nIntTmp, &num, &faceSplit, &queueM, &np, nTan1, nTan2);
				//printf("\n\nprofilo %d ricalcolato\n",z+1);
				if(z == 0)
					count[z] = num; //nInt - nIntTmp;
				else
					count[z] = num; //nInt - acc - nIntTmp;
				acc = acc + count[z];
			}

			break;
		}
	}

	k--;

	mesh_a = (Mod_SubdivMesh*)malloc(sizeof(Mod_SubdivMesh));
	mesh_b = (Mod_SubdivMesh*)malloc(sizeof(Mod_SubdivMesh));
	mesh_1->mod_copyMesh(mesh_a);
	mesh_2->mod_copyMesh(mesh_b);

	/* Viene inserito il profilo ottenuto dall'intersezione, tale
       operazione richiede che si parta da un punto situato su un edge
       della mesh, quindi per la seconda mesh si scarta il primo
       spostandolo in coda. */
	//Inserimento di tutti i profili di intersezione
	//dopo aver inserito un profilo, gli indexEdge e indexFace dei punti cambiano,devo aggiornare il profilo successivo
	for(z=0;z<k;z++){
		if(profiles[z]!=NULL){
			mesh_1 = gen_insertProfile(mesh_1, EM1FM2, profiles, count[z], z, k,
					EdgeMesh1_FaceMesh2, EdgeMesh2_FaceMesh1);

			//Aggiorno gli indexFace di interFace
			for(m=z;m<k;m++){
				tmp = profiles[m];     //profilo successivo
				while(tmp!=NULL){
					tmpEMFM = EdgeMesh2_FaceMesh1;
					while(tmpEMFM!=NULL){
						if((float)tmpEMFM->v.x == (float)tmp->point->v.x &&
								(float)tmpEMFM->v.y == (float)tmp->point->v.y &&
								(float)tmpEMFM->v.z == (float)tmp->point->v.z &&
								tmp->queueMesh == EM2FM1){
							//printf("p: %g %g %g -F %d --> %d\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z,tmpEMFM->indexFace,tmp->point->indexFace);
							tmpEMFM->indexFace = tmp->point->indexFace;         //aggiorna indexFace
						}
						tmpEMFM=tmpEMFM->next;
					}
					tmp=tmp->next;
				}
			}
			//Aggiorno gli indexEdge di interEdge
			for(m=z;m<k;m++){
				tmp = profiles[m];     //profilo successivo
				while(tmp!=NULL){
					tmpEMFM = EdgeMesh1_FaceMesh2;
					while(tmpEMFM!=NULL){
						if((float)tmpEMFM->v.x == (float)tmp->point->v.x &&
								(float)tmpEMFM->v.y == (float)tmp->point->v.y &&
								(float)tmpEMFM->v.z == (float)tmp->point->v.z &&
								tmp->queueMesh == EM1FM2){
							//printf("p: %g %g %g -E %d --> %d\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z,tmpEMFM->indexEdge,tmp->point->indexEdge);
							tmpEMFM->indexEdge = tmp->point->indexEdge;
						}
						tmpEMFM=tmpEMFM->next;
					}
					tmp=tmp->next;
				}
			}
		}
	}

	mesh_1->mod_save("mesh1profile",filepath1);
	// printf("%d\n",mesh_2->nVert);
	// printf("address %p\n",(void*)mesh_1);
	// printf("address %p\n",(void*)mesh_2);
	//Mod_SubdivMesh *nM1[k+1];
	vector<Mod_SubdivMesh*> nM1;
	tmpM = gen_splitMesh(mesh_1, &nM1, profiles, k);
	nM1.push_back(tmpM);
	// printf("%d\n",mesh_2->nVert);

#if DEBUG_GLUE
	printf("\n*********************\n");  fflush(stdout);
	printf("End split first mesh!\n");  fflush(stdout);
	printf("*********************\n\n");  fflush(stdout);
#endif

	for(z=0;z<k;z++){     //Inserimento di tutti i profili di intersezione
		if(profiles[z]!=NULL){
			acc = 0;
			acc1 = 0;
			tmp = profiles[z];
			while(tmp){
				acc++;  // conto punti profilo
				if(tmp->point->tan == 1)
					acc1++;	// conto punti profilo tangenti
				tmp = tmp->next;
			}
			/* Se il profilo non è composto da soli punti tangenti,
			 * si determina un punto della poligonale che incida
			 su un edge della stessa. */
			while (acc!=acc1 && profiles[z]->queueMesh != EM2FM1) {
				tmp = profiles[z];
				while (tmp->next) {
					tmp = tmp->next;
				}
				tmp->next = profiles[z];
				profiles[z] = profiles[z]->next;
				tmp->next->next = NULL;
			}


			mesh_2 = gen_insertProfile(mesh_2, EM2FM1, profiles, count[z], z, k,
					EdgeMesh2_FaceMesh1, EdgeMesh1_FaceMesh2);

			//Aggiorno gli indexFace di interFace
			for(m=z;m<k;m++){
				tmp = profiles[m];     //profilo successivo
				while(tmp!=NULL){
					tmpEMFM = EdgeMesh1_FaceMesh2;
					while(tmpEMFM!=NULL){
						if((float)tmpEMFM->v.x == (float)tmp->point->v.x &&
								(float)tmpEMFM->v.y == (float)tmp->point->v.y &&
								(float)tmpEMFM->v.z == (float)tmp->point->v.z &&
								tmp->queueMesh==EM1FM2){
							//printf("p: %g %g %g -F %d --> %d\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z,tmpEMFM->indexFace,tmp->point->indexFace);
							tmpEMFM->indexFace = tmp->point->indexFace;         //aggiorna indexFace
						}
						tmpEMFM=tmpEMFM->next;
					}
					tmp=tmp->next;
				}
			}
			//Aggiorno gli indexEdge di interEdge
			for(m=z;m<k;m++){
				tmp = profiles[m];     //profilo successivo
				while(tmp!=NULL){
					tmpEMFM = EdgeMesh2_FaceMesh1;
					while(tmpEMFM!=NULL){
						if((float)tmpEMFM->v.x == (float)tmp->point->v.x &&
								(float)tmpEMFM->v.y == (float)tmp->point->v.y &&
								(float)tmpEMFM->v.z == (float)tmp->point->v.z &&
								tmp->queueMesh == EM2FM1){
							//  printf("p: %g %g %g -E: %d --> %d\n",tmp->point->v.x,tmp->point->v.y,tmp->point->v.z,tmpEMFM->indexEdge,tmp->point->indexEdge);
							tmpEMFM->indexEdge = tmp->point->indexEdge;
						}
						tmpEMFM=tmpEMFM->next;
					}
					tmp=tmp->next;
				}
			}
		}
	}

	printf("%d\n",mesh_2->nVert);
	for(int t=1;t<=mesh_2->nVert;t++)
		printf("%g %g %g\n",mesh_2->vert[t].x,mesh_2->vert[t].y,mesh_2->vert[t].z);

	mesh_2->mod_save("mesh2profile",filepath2);

	//Mod_SubdivMesh *nM2[k+1];
	vector<Mod_SubdivMesh*> nM2;
	 tmpM = gen_splitMesh(mesh_2, &nM2, profiles, k);
	 nM2.push_back(tmpM);

	/* Creo dei patch formati dalle sole facce tangenti */
	vector<Mod_SubdivMesh*> tanPatch;
	Mod_SubdivMesh *faceMesh = NULL;
	for(z=1;z<=mesh_a->nFace;z++){
		if(mesh_a->face[z].tan == 1){
			faceMesh = (Mod_SubdivMesh*)malloc(sizeof(Mod_SubdivMesh));
			faceMesh->nVert = mesh_a->face[z].nVert;
			faceMesh->vert = (Vertex*)malloc((faceMesh->nVert+1)*sizeof(Vertex));
			faceMesh->nEdge = faceMesh->nVert;
			faceMesh->edge = (Edge*)malloc((faceMesh->nVert+1)*sizeof(Edge));
			faceMesh->nFace = 1;
			faceMesh->face = (Face*)malloc(2*sizeof(Face));
			faceMesh->face[1].nVert = mesh_a->face[z].nVert;
			for(h=0;h<mesh_a->face[z].nVert;h++){
				faceMesh->vert[h+1].x = mesh_a->vert[mesh_a->face[z].vert[h]].x;
				faceMesh->vert[h+1].y = mesh_a->vert[mesh_a->face[z].vert[h]].y;
				faceMesh->vert[h+1].z = mesh_a->vert[mesh_a->face[z].vert[h]].z;
				faceMesh->vert[h+1].bound = 1;
				faceMesh->face[1].vert[h] = h+1;
			}
			for(h=1;h<=faceMesh->nVert;h++){
				if(h<faceMesh->nVert){
					faceMesh->edge[h].vert[0] = h;
					faceMesh->edge[h].vert[1] = h+1;
				}
				else{
					faceMesh->edge[h].vert[0] = h;
					faceMesh->edge[h].vert[1] = 1;
				}
				faceMesh->edge[h].neigh[0] = 1;
				faceMesh->edge[h].neigh[1] = 0;
			}
			tanPatch.push_back(faceMesh);
		}
	}

	printf("----CLASSIFICAZIONE----\n");
	/* Uso due array per classificare i patch, i-esimo elemento ==1 indica che il patch
       appartiene all'intersezione delle due mesh */
	//int m1Patch[k+1];
	vector<int> m1Patch(k+1);
	//int m2Patch[k+1];
	vector<int> m2Patch(k+1);
	for(z=0;z<=k;z++){
		m1Patch[z]=0;
		m2Patch[z]=0;
	}
	vector<Vertex> vx;
	Vertex vert;
	// Punti di supporto
	Vertex pnt0,pnt1,pnt2,tmpPnt1,tmpPnt2;
	pnt1.x = 999999;
	pnt1.y = 999999;
	pnt1.z = 999999;
	// Se non ci sono profili di intersezione correggo il valore di k
	if(k==1 && profiles[0]==NULL){
		k = 0;
	}
	// Classifico ciascun patch
	for(z=0;z<=k;z++){
		/*
          Per ogni patch ottenuto dalla mesh1,controllo se un suo punto non tangente diverso da uno
          dei punti del profilo si trova dentro la mesh2 (ogni patch è interamente dentro o interamente
          fuori dalla zona di intersezione).
          Uso la funzione che verifica se un segmento con estremi p0 p1 interseca una faccia,
          segmentCrossPolygon
          p0 è il punto che devo testare per l'appartenenza alla mesh
          p1 lo prendo molto distante,serve solo per dare una direzione
          Ripeto per ogni faccia della mesh: numero di intersezioni dispari -> p0 interno alla mesh
          Se c'è intersezione su un vertice o su un edge devo contare l'intersezione come una sola
          Quindi:
          1) prendo uno dei vertici del patch (non appartenente ad un profilo)
          2) uso la segmentcrosspolygon per vedere dove si trova il punto rispetto alle mesh originali

          Se il patch è piano, fallisce perchè non c'è un punto non appartenente al profilo di intersezione
          Se non trova un punto da usare vuol dire che sono in questo caso:
          -> Il patch appartiene all'intersezione
          Invece di mettere a 1 il valore nell'array di classificazione, lo metto a 2 per
          poter discriminare i patch più avanti

          Nel caso di patch costituiti da soli punti in tangenza, una delle due mesh avrà il patch di
          intersezione costituito da soli punti del profilo (l'altra mesh no,a causa dell'ambiguità di
          costruzione del profilo,per cui in una faccia tangente considero solo una porzione degli edge
          e non tutto). Tale patch va classificato come 1 e non come 2. Per fare ciò,scorro il profilo
          e controllo la complanarità dei punti del profilo.
		 */
		for(m=1;m<=nM1[z]->nVert;m++){
			if(nM1[z]->vert[m].tan==1) continue;
			acc=0;
			for(h=0;h<k;h++){
				tmp=profiles[h];
				while(tmp){
					if( (float)nM1[z]->vert[m].x == (float)tmp->point->v.x &&
							(float)nM1[z]->vert[m].y == (float)tmp->point->v.y &&
							(float)nM1[z]->vert[m].z == (float)tmp->point->v.z ){
						acc++;
						break;
					}
					tmp=tmp->next;
				}
			}
			if(acc==0) break;
		}

		if(m > nM1[z]->nVert){
			vx.clear();
			for(h=1;h<=nM1[z]->nVert;h++){
				vx.push_back(nM1[z]->vert[h]);
			}
			if(gen_complaneVectorTest(vx)){
				m1Patch[z]=2;
			}
			else{
				printf("nM1) Patch Tan\n");
				m1Patch[z]=1;
			}
		}
		else{
			// nM1[z]->vert[m] è un punto del patch che non appartiene ad alcun profilo
			acc=0;
			acc1=0;
			pnt0.x = nM1[z]->vert[m].x;
			pnt0.y = nM1[z]->vert[m].y;
			pnt0.z = nM1[z]->vert[m].z;
			printf("nM1) Punto del patch non appartenente al profilo: %g %g %g \n",pnt0.x,pnt0.y,pnt0.z);
			for(h=1;h<=mesh_b->nFace;h++){
				if(gen_segmentCrossPolygon(mesh_b,h,pnt0,pnt1,&pnt2)){
					//controllo se il punto di intersezione si trova su un edge della faccia
					for(t=0;t<mesh_b->face[h].nVert;t++){

						tmpPnt1.x=mesh_b->vert[mesh_b->edge[mesh_b->face[h].edge[t]].vert[0]].x;
						tmpPnt1.y=mesh_b->vert[mesh_b->edge[mesh_b->face[h].edge[t]].vert[0]].y;;
						tmpPnt1.z=mesh_b->vert[mesh_b->edge[mesh_b->face[h].edge[t]].vert[0]].z;;
						tmpPnt2.x=mesh_b->vert[mesh_b->edge[mesh_b->face[h].edge[t]].vert[1]].x;
						tmpPnt2.y=mesh_b->vert[mesh_b->edge[mesh_b->face[h].edge[t]].vert[1]].y;;
						tmpPnt2.z=mesh_b->vert[mesh_b->edge[mesh_b->face[h].edge[t]].vert[1]].z;;

						if(gen_pointDsegment(pnt2,tmpPnt1,tmpPnt2,tollerance)){
							acc1++;
							break;
						}
					}
					acc++;
				}
			}
			if((acc-(acc1/2))%2!=0) m1Patch[z]=1;
		}
		//Ripeto per i patch dell'altra mesh
		for(m=1;m<=nM2[z]->nVert;m++){
			if(nM2[z]->vert[m].tan==1) continue;
			acc=0;
			for(h=0;h<k;h++){
				tmp=profiles[h];
				while(tmp){
					if( (float)nM2[z]->vert[m].x == (float)tmp->point->v.x &&
							(float)nM2[z]->vert[m].y == (float)tmp->point->v.y &&
							(float)nM2[z]->vert[m].z == (float)tmp->point->v.z ){
						acc++;
						break;
					}
					tmp=tmp->next;
				}
			}
			if(acc==0) break;
		}
		if(m > nM2[z]->nVert){
			vx.clear();
			for(h=1;h<=nM2[z]->nVert;h++){
				vert.x = nM2[z]->vert[h].x;
				vert.y = nM2[z]->vert[h].y;
				vert.z = nM2[z]->vert[h].z;
				vx.push_back(vert);
			}
			if(gen_complaneVectorTest(vx)){
				m2Patch[z]=2;
			}
			else{
				printf("nM2) Patch Tan\n");
				m2Patch[z]=1;
			}
		}
		else{
			// nM2[z]->vert[m] è un punto del patch che non appartiene ad alcun profilo
			acc=0;
			acc1=0;
			pnt0.x = nM2[z]->vert[m].x;
			pnt0.y = nM2[z]->vert[m].y;
			pnt0.z = nM2[z]->vert[m].z;
			printf("nM2) Punto del patch non appartenente al profilo: %g %g %g \n",pnt0.x,pnt0.y,pnt0.z);
			for(h=1;h<=mesh_a->nFace;h++){
				if(gen_segmentCrossPolygon(mesh_a,h,pnt0,pnt1,&pnt2)){
					printf("nM2) Punto del patch interseca faccia: %g %g %g \n",pnt0.x,pnt0.y,pnt0.z);
					//controllo se il punto di intersezione si trova su un edge della faccia
					for(t=0;t<mesh_a->face[h].nVert;t++){

						tmpPnt1.x=mesh_a->vert[mesh_a->edge[mesh_a->face[h].edge[t]].vert[0]].x;
						tmpPnt1.y=mesh_a->vert[mesh_a->edge[mesh_a->face[h].edge[t]].vert[0]].y;
						tmpPnt1.z=mesh_a->vert[mesh_a->edge[mesh_a->face[h].edge[t]].vert[0]].z;
						tmpPnt2.x=mesh_a->vert[mesh_a->edge[mesh_a->face[h].edge[t]].vert[1]].x;
						tmpPnt2.y=mesh_a->vert[mesh_a->edge[mesh_a->face[h].edge[t]].vert[1]].y;;
						tmpPnt2.z=mesh_a->vert[mesh_a->edge[mesh_a->face[h].edge[t]].vert[1]].z;;

						if(gen_pointDsegment(pnt2,tmpPnt1,tmpPnt2,tollerance)){
							acc1++;
							break;
						}
					}

					//MORENO: devo controllare vertici e edge: la prima intersezione da cui esco è un +1, le altre intersezioni su edge e vertici sono +2
					//lista punti intersezione non duplicati,  alla fine conto gli elementi della lista e ho il numero di intersezioni

					acc++;
				}
			}
			if((acc-(acc1/2))%2!=0) m2Patch[z]=1;
		}
	}
	printf("Risultato classificazione:\n");
	for(z=0;z<=k;z++)
		printf("%d   %d\n",m1Patch[z],m2Patch[z]);

	printf("----CLASSIFICAZIONE----\n");
	/* Ora è possibile unire i patch delle due mesh, combinando i rispettivi
         	 patch.
        	- unione M1+M2-(le parti che si intersecano)
        	- differenza M1-M2
        	- differenza M2-M1
        	- intersezione
	 */
	Mod_SubdivMesh *res = NULL;
	vector<Mod_SubdivMesh*> mergeMesh(2);
	vector<Mod_SubdivMesh*> meshArray(k+1);
	//Unione
	printf("-----UNIONE------\n");
	for(h=0;h<=k;h++){
		if(m1Patch[h]!=0) continue;
		mesh_g[0] = nM1[h];
		for(z=0;z<=k;z++){
			if(m2Patch[z]==0){
				vneigh = gen_searchVneighbour(mesh_g[0], nM2[z], tollerance);
				if(vneigh!=NULL){
					if (!gen_normalCheckDouble(mesh_g[0], nM2[z], vneigh)) gen_reverseNormal(nM2[z]);
					mesh_g[0] = gen_glueCoupleMesh(mesh_g[0], nM2[z], &vneigh);
				}
			}
		}
		if(res!=NULL){
			mergeMesh[0] = res;
			mergeMesh[1] = mesh_g[0];
			res = gen_meshAdd(&mergeMesh,2);
		}
		else
			res = mesh_g[0];
	}
	if(res==NULL){
		// sono nel caso di sola tangenza,in questo caso uno dei due patch è interno all'altro
		if(m1Patch[0]==0)
			res = nM1[0];
		else if(m2Patch[0]==0)
			res = nM2[0];
	}
	printf("Aggiungo le facce tangenti al risultato\n");
	for(std::vector<double>::size_type d=0;d<tanPatch.size();d++){
		vneigh = gen_searchVneighbour(res, tanPatch[d], tollerance);
		if(vneigh!=NULL){
			if (!gen_normalCheckDouble(res, tanPatch[d], vneigh)) gen_reverseNormal(tanPatch[d]);
			res = gen_glueCoupleMesh(res, tanPatch[d], &vneigh);
		}
	}
	mesh_g[0]=res;
	res->mod_save("mesh1+mesh2",filepath1);

	//Differenza 1
	res = NULL;
	printf("-----DIFFERENZA 1------\n");
	for(h=0;h<=k;h++){
		if(m1Patch[h]!=0) continue;
		mesh_g[1] = nM1[h];
		for(z=0;z<=k;z++){
			if(m2Patch[z]!=0){
				vneigh = gen_searchVneighbour(mesh_g[1], nM2[z], tollerance);
				if(vneigh!=NULL){
					if (!gen_normalCheckDouble(mesh_g[1], nM2[z], vneigh)) gen_reverseNormal(nM2[z]);
					mesh_g[1] = gen_glueCoupleMesh(mesh_g[1], nM2[z], &vneigh);
				}
			}
		}
		if(res!=NULL){
			mergeMesh[0] = res;
			mergeMesh[1] = mesh_g[1];
			res = gen_meshAdd(&mergeMesh,2);
		}
		else
			res = mesh_g[1];
	}
	if(res==NULL){
		// sono nel caso di sola tangenza,in questo caso uno dei due patch è interno all'altro
		res = nM1[0];
	}
	mesh_g[1]=res;
	res->mod_save("mesh1-mesh2",filepath1);

	//Differenza 2
	res = NULL;
	printf("-----DIFFERENZA 2------\n");
	for(z=0;z<=k;z++){
		if(m2Patch[z]!=0) continue;
		mesh_g[2] = nM2[z];
		for(h=0;h<=k;h++){
			if(m1Patch[h]!=0){
				vneigh = gen_searchVneighbour(nM1[h], mesh_g[2], tollerance);
				if(vneigh!=NULL){
					if (!gen_normalCheckDouble(nM1[h], mesh_g[2], vneigh)) gen_reverseNormal(nM1[h]);
					mesh_g[2] = gen_glueCoupleMesh(nM1[h], mesh_g[2], &vneigh);
				}
			}
		}
		if(res!=NULL){
			mergeMesh[0] = res;
			mergeMesh[1] = mesh_g[2];
			res = gen_meshAdd(&mergeMesh,2);
		}
		else
			res = mesh_g[2];
	}
	if(res==NULL){
		// sono nel caso di sola tangenza,in questo caso uno dei due patch è interno all'altro
		res = nM2[0];
	}
	mesh_g[2]=res;
	res->mod_save("mesh2-mesh1",filepath1);

	//Intersezione
	res = NULL;
	printf("-----INTERSEZIONE------\n");
	m=0;
	for(h=0;h<=k;h++){
		if(m1Patch[h]==0) continue;
		meshArray[m] = nM1[h];
		for(z=0;z<=k;z++){
			if(m2Patch[z]==0) continue;
			vneigh = gen_searchVneighbour(meshArray[m], nM2[z], tollerance);
			if(vneigh!=NULL){
				//si invertono le normali (sono state invertite precedentemente nelle differenze)
				gen_reverseNormal(meshArray[m]);
				gen_reverseNormal(nM2[z]);
				meshArray[m] = gen_glueCoupleMesh(meshArray[m], nM2[z], &vneigh);
			}
		}
		m++;
	}
	/* Devo avere i pezzi dell'intersezione in un unica mesh */
	if(k>0){
		mesh_g[3] = gen_meshAdd(&meshArray,m);
		res = mesh_g[3];
		for(std::vector<double>::size_type d=0;d<tanPatch.size();d++){
			vneigh = gen_searchVneighbour(res, tanPatch[d], tollerance);
			if(vneigh!=NULL){
				if (!gen_normalCheckDouble(res, tanPatch[d], vneigh)) gen_reverseNormal(tanPatch[d]);
				res = gen_glueCoupleMesh(res, tanPatch[d], &vneigh);
			}
		}
		mesh_g[3] = res;
	}
	else{
		mesh_g[3] = tanPatch[0];
		res = mesh_g[3];
		for(std::vector<double>::size_type d=1;d<tanPatch.size();d++){
			vneigh = gen_searchVneighbour(res, tanPatch[d], tollerance);
			if(vneigh!=NULL){
				if (!gen_normalCheckDouble(res, tanPatch[d], vneigh)) gen_reverseNormal(tanPatch[d]);
				res = gen_glueCoupleMesh(res, tanPatch[d], &vneigh);
			}
		}
		mesh_g[3] = res;
	}
	mesh_g[3]->mod_save("mesh1*mesh2",filepath1);

	free(mesh_a->vert);	free(mesh_a->face);
	free(mesh_a->edge);	free(mesh_a);

	free(mesh_b->vert);	free(mesh_b->face);
	free(mesh_b->edge);	free(mesh_b);

	printf("apply booleans END\n");

	result.push_back(mesh_g[0]);
	result.push_back(mesh_g[1]);
	result.push_back(mesh_g[2]);
	result.push_back(mesh_g[3]);

	return result;
}

/* Procedura per la ricerca dei vertici incidenti su edge tra due mesh. */
void gen_searchEneighbour(Mod_SubdivMesh **mesh_1, Mod_SubdivMesh **mesh_2, float toll) {

	e_bound *Qbound_mnv, *Qbound_Mnv, *qtmp, *qtmpp;
	q_point *ptmp, *prev;
	Mod_SubdivMesh *mnv_mesh, *Mnv_mesh;
	Vertex *new_vert;
	Face *new_face;
	Vertex v, p0, p1;
	int *vneigh_mM, *vneigh_Mm;
	int i, j, k, nVinm, nVinM, mnv, Mnv, face, vInsert;
	char m, M;
	bool insert;

#if DEBUG_GLUE
	printf("SEARCH_2---------------------------->>\n");
#endif

	nVinm = nVinM = 0;

	if ( (*mesh_2)->nVert <= (*mesh_1)->nVert ) {
		mnv = (*mesh_2)->nVert;  Mnv = (*mesh_1)->nVert;
		mnv_mesh = *mesh_2;  Mnv_mesh = *mesh_1;
		m = '2';  M = '1';
	} else {
		mnv = (*mesh_1)->nVert;  Mnv = (*mesh_2)->nVert;
		mnv_mesh = *mesh_1;  Mnv_mesh = *mesh_2;
		m = '1';  M = '2';
	}

	/* Collezione degli edge di bordo */
	Qbound_mnv = gen_findEbound(mnv_mesh);
	Qbound_Mnv = gen_findEbound(Mnv_mesh);

	/* Ricerca dei possibili vertici vicini, vneigh_?:
     - mM = indica che l'indice i dell'array si riferisce alla mesh
            con min num vertex */
	vneigh_mM = gen_searchVneighbour(*mesh_1, *mesh_2, toll);
	/* - Mm = indica che l'indice i dell'array si riferisce alla mesh
            con max num vertex  */
	if (vneigh_mM) {
		vneigh_Mm = (int*)calloc((Mnv + 1), sizeof(int));
		if (!vneigh_Mm) ErrorMessage();
		for (i=1; i <= mnv; i++) {
			if (vneigh_mM[i]) vneigh_Mm[vneigh_mM[i]] = i;
		}
	} else vneigh_Mm = NULL;

	/* Controllo dei vertici vicini a edge per entrambe le mesh */
	for (i=1; i <= mnv_mesh->nVert; i++) {
		if ( mnv_mesh->vert[i].bound &&
				((vneigh_mM && !vneigh_mM[i]) || !vneigh_mM ) ) {
			/* per i soli vertici di bordo, che non hanno vicini o perche non ci sono
         vertici vicini a vertici */
			v.x = mnv_mesh->vert[i].x;
			v.y = mnv_mesh->vert[i].y;
			v.z = mnv_mesh->vert[i].z;
			qtmp = Qbound_Mnv;

			do {
				p0.x = Mnv_mesh->vert[(Mnv_mesh->edge[qtmp->edge].vert[0])].x;
				p0.y = Mnv_mesh->vert[(Mnv_mesh->edge[qtmp->edge].vert[0])].y;
				p0.z = Mnv_mesh->vert[(Mnv_mesh->edge[qtmp->edge].vert[0])].z;
				p1.x = Mnv_mesh->vert[(Mnv_mesh->edge[qtmp->edge].vert[1])].x;
				p1.y = Mnv_mesh->vert[(Mnv_mesh->edge[qtmp->edge].vert[1])].y;
				p1.z = Mnv_mesh->vert[(Mnv_mesh->edge[qtmp->edge].vert[1])].z;
				if (gen_pointDsegment(v, p0, p1, toll)) {

					if (!qtmp->insV) { /* è il primo punto da inserire */

						qtmp->insV = (q_point*)malloc(sizeof(q_point));
						if (!qtmp->insV) ErrorMessage();
						else {
							qtmp->insV->v.x = v.x;
							qtmp->insV->v.y = v.y;
							qtmp->insV->v.z = v.z;
							qtmp->insV->indexFace = qtmp->insV->indexEdge = 0;
							qtmp->insV->next = NULL;
						}

					} else { /* inserisce il punto nella coda */

						insert = false;
						ptmp = qtmp->insV;
						p1.x = qtmp->insV->v.x;
						p1.y = qtmp->insV->v.y;
						p1.z = qtmp->insV->v.z;

						do {
							if (gen_pointDsegment(v, p0, p1, toll)) insert = true;
							else {
								prev = ptmp;
								ptmp = ptmp->next;
								p0.x = p1.x;
								p0.y = p1.y;
								p0.z = p1.z;
								p1.x = ptmp->v.x;
								p1.y = ptmp->v.y;
								p1.z = ptmp->v.z;
							}
						} while (!insert);

						if (ptmp == qtmp->insV) {
							ptmp = (q_point*)malloc(sizeof(q_point));
							if (!ptmp) ErrorMessage();
							else {
								ptmp->v.x = v.x;
								ptmp->v.y = v.y;
								ptmp->v.z = v.z;
								ptmp->indexFace = ptmp->indexEdge = 0;
								ptmp->next = qtmp->insV;
								qtmp->insV = ptmp;
							}
						} else {
							prev->next = (q_point*)malloc(sizeof(q_point));
							if (!prev->next) ErrorMessage();
							else {
								prev->next->v.x = v.x;
								prev->next->v.y = v.y;
								prev->next->v.z = v.z;
								prev->next->indexFace = prev->next->indexEdge = 0;
								prev->next->next = ptmp;
							}
						}
					}

					nVinM++;

#if DEBUG_GLUE
					printf("Find: vertex %d mesh %c neighbour edge %d mesh %c  (X,Y,Z)=(%g %g %g)\n",
							i,m,qtmp->edge,M,v.x,v.y,v.z);
#endif
				}
				qtmp = qtmp->next;
			} while (qtmp != Qbound_Mnv);
		}
	}

	for (i=1; i <= Mnv_mesh->nVert; i++) {
		if ( Mnv_mesh->vert[i].bound &&
				((vneigh_Mm && !vneigh_Mm[i]) || !vneigh_Mm ) ) {
			v.x = Mnv_mesh->vert[i].x;
			v.y = Mnv_mesh->vert[i].y;
			v.z = Mnv_mesh->vert[i].z;
			qtmp = Qbound_mnv;

			do {
				p0.x = mnv_mesh->vert[(mnv_mesh->edge[qtmp->edge].vert[0])].x;
				p0.y = mnv_mesh->vert[(mnv_mesh->edge[qtmp->edge].vert[0])].y;
				p0.z = mnv_mesh->vert[(mnv_mesh->edge[qtmp->edge].vert[0])].z;
				p1.x = mnv_mesh->vert[(mnv_mesh->edge[qtmp->edge].vert[1])].x;
				p1.y = mnv_mesh->vert[(mnv_mesh->edge[qtmp->edge].vert[1])].y;
				p1.z = mnv_mesh->vert[(mnv_mesh->edge[qtmp->edge].vert[1])].z;
				if (gen_pointDsegment(v, p0, p1, toll)) {

					if (!qtmp->insV) { /* è il primo punto da inserire */

						qtmp->insV = (q_point*)malloc(sizeof(q_point));
						if (!qtmp->insV) ErrorMessage();
						else {
							qtmp->insV->v.x = v.x;
							qtmp->insV->v.y = v.y;
							qtmp->insV->v.z = v.z;
							qtmp->insV->indexFace = qtmp->insV->indexEdge = 0;
							qtmp->insV->next = NULL;
						}

					} else { /* inserisce il punto nella coda */

						insert = false;
						ptmp = qtmp->insV;
						p1.x = qtmp->insV->v.x;
						p1.y = qtmp->insV->v.y;
						p1.z = qtmp->insV->v.z;

						do {
							if (gen_pointDsegment(v, p0, p1, toll)) insert = true;
							else {
								prev = ptmp;
								ptmp = ptmp->next;
								p0.x = p1.x;
								p0.y = p1.y;
								p0.z = p1.z;
								p1.x = ptmp->v.x;
								p1.y = ptmp->v.y;
								p1.z = ptmp->v.z;
							}
						} while (!insert);

						if (ptmp == qtmp->insV) {
							ptmp = (q_point*)malloc(sizeof(q_point));
							if (!ptmp) ErrorMessage();
							else {
								ptmp->v.x = v.x;
								ptmp->v.y = v.y;
								ptmp->v.z = v.z;
								ptmp->indexFace = ptmp->indexEdge = 0;
								ptmp->next = qtmp->insV;
								qtmp->insV = ptmp;
							}
						} else {
							prev->next = (q_point*)malloc(sizeof(q_point));
							if (!prev->next) ErrorMessage();
							else {
								prev->next->v.x = v.x;
								prev->next->v.y = v.y;
								prev->next->v.z = v.z;
								prev->next->indexFace = prev->next->indexEdge = 0;
								prev->next->next = ptmp;
							}
						}
					}

					nVinm++;

#if DEBUG_GLUE
					printf("Find: vertex %d mesh %c neighbour edge %d mesh %c  (X,Y,Z)=(%g %g %g)\n",
							i,M,qtmp->edge,m,v.x,v.y,v.z);
#endif
				}
				qtmp = qtmp->next;
			} while (qtmp != Qbound_mnv);
		}
	}


#if DEBUG_GLUE
	printf("n° %d new vertexes to insert in mesh %c\nn° %d new vertexes to insert in mesh %c\n",
			nVinm, m, nVinM, M);
#endif


	/* Spazio per i nuovi vertici da inserire nella prima mesh... */
	new_vert  = (Vertex*) malloc((mnv_mesh->nVert + 1 + nVinm) * sizeof(Vertex));
	if (!new_vert) ErrorMessage();
	/* ... copia dei vecchi vertici ... */
	for (i=1; i <= mnv_mesh->nVert; i++) {
		new_vert[i].x = mnv_mesh->vert[i].x;
		new_vert[i].y = mnv_mesh->vert[i].y;
		new_vert[i].z = mnv_mesh->vert[i].z;
	}
	/* ... inserimento dei nuovi e aggiornamento delle faccette ... */
	qtmp = Qbound_mnv;
	do {
		if (qtmp->insV) {

			/* ... inserimento dell'indice di vertex nella faccetta ... */
			k = 0;
			face = mnv_mesh->edge[qtmp->edge].neigh[0];  /* indice della faccetta da correggere */
			new_face = (Face*) malloc(sizeof(Face));
			if (!new_face) ErrorMessage();
			for (j=0; j < mnv_mesh->face[face].nVert; j++) {

				if ( mnv_mesh->face[face].vert[j] !=
						mnv_mesh->edge[qtmp->edge].vert[0]) {
					new_face->vert[k] = mnv_mesh->face[face].vert[j];
					k++;

				} else {
					new_face->vert[k] = mnv_mesh->face[face].vert[j];
					k++;

					ptmp = qtmp->insV;
					vInsert = 0;
					do {
						new_vert[i].x = ptmp->v.x;
						new_vert[i].y = ptmp->v.y;
						new_vert[i].z = ptmp->v.z;
						new_face->vert[k] = i;

#if DEBUG_GLUE
						printf("New vertex %d (%g %g %g) insert in face %d of mesh %c\n",
								i,new_vert[i].x,new_vert[i].y,new_vert[i].z,face, m);
#endif

						k++;
						i++;
						vInsert++;
						ptmp = ptmp->next;
					} while (ptmp);
				}
			}

			mnv_mesh->face[face].nVert += vInsert;

#if DEBUG_GLUE
			printf("New face: ");
#endif

			for (j=0; j < mnv_mesh->face[face].nVert; j++) {
				mnv_mesh->face[face].vert[j] = new_face->vert[j];
#if DEBUG_GLUE
				printf("%d ",mnv_mesh->face[face].vert[j]);
#endif
			}
#if DEBUG_GLUE
			printf("\n");
#endif
			free(new_face);

		}
		qtmp = qtmp->next;
	} while (qtmp != Qbound_mnv);
	/* ... correzione cardinalità del numero di vertici della mesh. */
	mnv_mesh->nVert = mnv_mesh->nVert + nVinm;
	free(mnv_mesh->vert);
	mnv_mesh->vert = new_vert;


	/* Spazio per i nuovi vertici da inserire nella seconda mesh... */
	new_vert = NULL;
	new_vert  = (Vertex*) malloc((Mnv_mesh->nVert + 1 + nVinM) * sizeof(Vertex));
	if (!new_vert) ErrorMessage();
	/* ... copia dei vecchi vertici ... */
	for (i=1; i <= Mnv_mesh->nVert; i++) {
		new_vert[i].x = Mnv_mesh->vert[i].x;
		new_vert[i].y = Mnv_mesh->vert[i].y;
		new_vert[i].z = Mnv_mesh->vert[i].z;
	}
	/* ... inserimento dei nuovi e aggiornamento delle faccette ... */
	qtmp = Qbound_Mnv;
	do {
		if (qtmp->insV) {

			/* ... inserimento dell'indice di vertex nella faccetta ... */
			k = 0;
			face = Mnv_mesh->edge[qtmp->edge].neigh[0];  /* indice della faccetta da correggere */
			new_face = (Face*) malloc(sizeof(Face));
			if (!new_face) ErrorMessage();
			for (j=0; j < Mnv_mesh->face[face].nVert; j++) {

				if ( Mnv_mesh->face[face].vert[j] !=
						Mnv_mesh->edge[qtmp->edge].vert[0]) {
					new_face->vert[k] = Mnv_mesh->face[face].vert[j];
					k++;

				} else {
					new_face->vert[k] = Mnv_mesh->face[face].vert[j];
					k++;

					ptmp = qtmp->insV;
					vInsert = 0;
					do {
						new_vert[i].x = ptmp->v.x;
						new_vert[i].y = ptmp->v.y;
						new_vert[i].z = ptmp->v.z;
						new_face->vert[k] = i;

#if DEBUG_GLUE
						printf("New vertex %d (%g %g %g) insert in face %d of mesh %c\n",
								i,new_vert[i].x,new_vert[i].y,new_vert[i].z,face,M);
#endif

						k++;
						i++;
						vInsert++;
						ptmp = ptmp->next;
					} while (ptmp);
				}
			}

			Mnv_mesh->face[face].nVert += vInsert;

#if DEBUG_GLUE
			printf("New face: ");
#endif

			for (j=0; j < Mnv_mesh->face[face].nVert; j++) {
				Mnv_mesh->face[face].vert[j] = new_face->vert[j];
#if DEBUG_GLUE
				printf("%d ",Mnv_mesh->face[face].vert[j]);
#endif
			}
#if DEBUG_GLUE
			printf("\n");
#endif
			free(new_face);

		}
		qtmp = qtmp->next;
	} while (qtmp != Qbound_Mnv);
	/* ... correzione cardinalità del numero di vertici della mesh. */
	Mnv_mesh->nVert = Mnv_mesh->nVert + nVinM;
	free(Mnv_mesh->vert);
	Mnv_mesh->vert = new_vert;

	/* Ordinamento edge di bordo: operazione preliminare per il rilevamento
     di eventuali buchi che si sono formati nel collegamento dei bordi */
	gen_boundProfile(mnv_mesh, &Qbound_mnv);
	gen_boundProfile(Mnv_mesh, &Qbound_Mnv);


	/* TODO
     Ciclo di verifica buchi:

     per tutti gli edge della LISTA
       se un edge non ha vertici da inserire
         allora il suo predeccessore || il suo sucessore non devono avere vertici da inserire
         altrimenti utilizzo i loro vertici da inserire per creare nuove facce ?????????

     per tutti gli edge della LISTA
       se un edge non ha vertici da inserire
         allora il suo predeccessore || il suo sucessore non devono avere vertici da inserire
         altrimenti utilizzo i loro vertici da inserire per creare nuove facce ?????????

	 */

	if ( (*mesh_2)->nVert <= (*mesh_1)->nVert ) {
		*mesh_2 = mnv_mesh;  *mesh_1 = Mnv_mesh;
	} else {
		*mesh_1 = mnv_mesh;  *mesh_2 = Mnv_mesh;
	}

	(*mesh_1)->mod_LoadSubdivMesh();
	(*mesh_2)->mod_LoadSubdivMesh();

	if (Qbound_Mnv && Qbound_Mnv->prev && Qbound_Mnv->prev->next)
		Qbound_Mnv->prev->next = NULL;
	qtmp = Qbound_Mnv;
	while (qtmp) {
		qtmpp = qtmp;
		qtmp = qtmp->next;
		free(qtmpp);
	}

	if (Qbound_mnv && Qbound_mnv->prev && Qbound_mnv->prev->next)
		Qbound_mnv->prev->next = NULL;
	qtmp = Qbound_mnv;
	while (qtmp) {
		qtmpp = qtmp;
		qtmp = qtmp->next;
		free(qtmpp);
	}


#if DEBUG_GLUE
	printf("<<----------------------------SEARCH_2\n");
#endif

	return;
}

/* Funzione per la ricerca degli edge di bordo. */
e_bound* gen_findEbound(Mod_SubdivMesh *mesh) {

	int i;
	e_bound *Qbound, *ins, *tmp;

	Qbound = NULL;  ins = NULL;  tmp = NULL;

	/* per gli edge di bordo il secondo campo di neigh è 0 */
	for (i=1; i <= mesh->nEdge; i++) {
		if (!mesh->edge[i].neigh[1]) {
			tmp = (e_bound*) malloc(sizeof(e_bound));
			if (!tmp) ErrorMessage();
			tmp->edge = i;
			tmp->next = NULL;
			tmp->prev = NULL;
			tmp->insV = NULL;
			if (!Qbound) {
				Qbound = ins = tmp;
			} else {
				ins->next = tmp;
				tmp->prev = ins;
				ins = tmp;
			}
		}
	}

#if DEBUG_GLUE
	tmp = Qbound;
	while (tmp) {
		printf("Find bound edge: %d  v%d---v%d\n",
				tmp->edge,mesh->edge[tmp->edge].vert[0],
				mesh->edge[tmp->edge].vert[1]);
		tmp = tmp->next;
	}
#endif

	ins->next = Qbound;
	Qbound->prev = ins;

	return Qbound;
}

/* Funzione per il riordino degli edge di bordo,
   in modo da creare il profilo reale. */
e_bound* gen_boundProfile(Mod_SubdivMesh *mesh, e_bound **QEB) {

	int i, n, ins;
	e_bound *bound, *start, *nx, *pr;

	bound = NULL;  start = NULL;
	nx = NULL;  pr = NULL;
	n = ins = 0;

	/* primo elemento da cui ricostruire il bordo */
	bound = (*QEB);
	(*QEB)->next->prev = (*QEB)->prev;
	(*QEB)->prev->next = (*QEB)->next;
	(*QEB) = (*QEB)->next;
	bound->next = NULL;
	bound->prev = NULL;
	nx = pr = bound;

	/* numero degli elementi rimasti in coda */
	start = (*QEB);
	do {
		n++;
		start = start->next;
	} while (start != (*QEB));

#if DEBUG_GLUE
	printf("Number elements to order: %d\n",n+1);
#endif

	/* ciclo di riordino */
	do {

		ins = 0;

		/* ciclo di ricerca nuovo elemento da inserire */
		for (i=0; i < n; i++) {

			if (mesh->edge[nx->edge].vert[1] ==
					mesh->edge[(*QEB)->edge].vert[0]) { /* elemento in direzione 0->1 */

				nx->next = (*QEB);
				(*QEB)->next->prev = (*QEB)->prev;
				(*QEB)->prev->next = (*QEB)->next;
				(*QEB)->prev = nx;
				nx = (*QEB);
				if ((*QEB) != nx->next) (*QEB) = nx->next;
				else (*QEB) = NULL;
				nx->next = NULL;
				ins++;

			} else if (mesh->edge[pr->edge].vert[0] ==
					mesh->edge[(*QEB)->edge].vert[1]) { /* elemento in direzione 1->0 */

				pr->prev = (*QEB);
				(*QEB)->next->prev = (*QEB)->prev;
				(*QEB)->prev->next = (*QEB)->next;
				(*QEB)->next = pr;
				pr = (*QEB);
				if ((*QEB) != pr->prev->next) (*QEB) = pr->prev->next;
				else (*QEB) = NULL;
				pr->prev = NULL;
				ins++;

			} else { /* non è ancora possibile inserire l'elemento */
				(*QEB) = (*QEB)->next;
			}
		}

		n -= ins;   /* riduzione degli elementi tra cui cercare */

#if DEBUG_GLUE
		printf("Number elements to order: %d\n",n);
#endif

	} while (ins);

	/* chiusura del bordo */
	if (mesh->edge[nx->edge].vert[1] == mesh->edge[pr->edge].vert[0]) {
#if DEBUG_GLUE
		printf("Close Bound: E%d v%d---v%d in E%d v%d---v%d\n",
				nx->edge, mesh->edge[nx->edge].vert[0],mesh->edge[nx->edge].vert[1],
				pr->edge, mesh->edge[pr->edge].vert[0],
				mesh->edge[pr->edge].vert[1]); fflush(stdout);

#endif
		nx->next = pr;
		pr->prev = nx;
	} else printf("ERROR: close bound!!\n");

#if DEBUG_GLUE
	start = bound->prev;
	do {
		printf("Bound: E%d  v%d---v%d\n",bound->edge,
				mesh->edge[bound->edge].vert[0],
				mesh->edge[bound->edge].vert[1]); fflush(stdout);
		bound = bound->next;
	} while (bound != start);
	printf("Bound: E%d  v%d---v%d\n",bound->edge,
			mesh->edge[bound->edge].vert[0],
			mesh->edge[bound->edge].vert[1]); fflush(stdout);

#endif

	return bound;
}

// Compute the axis aligned bounding box
Vertex* gen_computeBoundingBox(Mod_SubdivMesh *mesh){

	Vertex* bb;		// bb[0] = bbmin , bb[1] = bbmax
	bb = (Vertex*)malloc(2*sizeof(Vertex));
	if(!bb) ErrorMessage();

	if ((*mesh).nVert == 0) return NULL;

	bb[0].x=bb[1].x=(*mesh).vert[1].x;
	bb[0].y=bb[1].y=(*mesh).vert[1].y;
	bb[0].z=bb[1].z=(*mesh).vert[1].z;

	for (int i=2; i<=(*mesh).nVert; i++){

		if (bb[0].x>(*mesh).vert[i].x) bb[0].x=(*mesh).vert[i].x;
		if (bb[0].y>(*mesh).vert[i].y) bb[0].y=(*mesh).vert[i].y;
		if (bb[0].z>(*mesh).vert[i].z) bb[0].z=(*mesh).vert[i].z;

		if (bb[1].x<(*mesh).vert[i].x) bb[1].x=(*mesh).vert[i].x;
		if (bb[1].y<(*mesh).vert[i].y) bb[1].y=(*mesh).vert[i].y;
		if (bb[1].z<(*mesh).vert[i].z) bb[1].z=(*mesh).vert[i].z;

	}

	return bb;

}

// Check if two AABB are colliding
bool gen_checkBoxCollision(Vertex *bb1, Vertex *bb2){

	//Check if Box1's max is greater or equal than Box2's min and Box1's min is less or equal than Box2's max
	return( bb1[1].x >= bb2[0].x &&
			bb1[0].x <= bb2[1].x &&
			bb1[1].y >= bb2[0].y &&
			bb1[0].y <= bb2[1].y &&
			bb1[1].z >= bb2[0].z &&
			bb1[0].z <= bb2[1].z );

}

/* Funzione che determina se una faccia si trova in un bounding box */
bool gen_faceInBox(Mod_SubdivMesh *mesh, int f, Vertex *bb){

	Vertex* bbf;		// bbf[0] = bbmin , bbf[1] = bbmax
	bbf = (Vertex*)malloc(2*sizeof(Vertex));
	if(!bbf) ErrorMessage();

	bbf[0].x=bbf[1].x=mesh->vert[mesh->face[f].vert[0]].x;
	bbf[0].y=bbf[1].y=mesh->vert[mesh->face[f].vert[0]].y;
	bbf[0].z=bbf[1].z=mesh->vert[mesh->face[f].vert[0]].z;

	for (int i=0; i<mesh->face[f].nVert; i++){

		if (bbf[0].x>mesh->vert[mesh->face[f].vert[i]].x) bbf[0].x=mesh->vert[mesh->face[f].vert[i]].x;
		if (bbf[0].y>mesh->vert[mesh->face[f].vert[i]].y) bbf[0].y=mesh->vert[mesh->face[f].vert[i]].y;
		if (bbf[0].z>mesh->vert[mesh->face[f].vert[i]].z) bbf[0].z=mesh->vert[mesh->face[f].vert[i]].z;

		if (bbf[1].x<mesh->vert[mesh->face[f].vert[i]].x) bbf[1].x=mesh->vert[mesh->face[f].vert[i]].x;
		if (bbf[1].y<mesh->vert[mesh->face[f].vert[i]].y) bbf[1].y=mesh->vert[mesh->face[f].vert[i]].y;
		if (bbf[1].z<mesh->vert[mesh->face[f].vert[i]].z) bbf[1].z=mesh->vert[mesh->face[f].vert[i]].z;

	}

	return gen_checkBoxCollision(bbf,bb);
}

/* Funzione che,date due facce complanari,ne determina la regione di sovrapposizione.
 * param[4] individua il piano in cui si trovano le due facce */
vector<Vertex> gen_faceOverlap(Mod_SubdivMesh **mesh1, Mod_SubdivMesh **mesh2, int f1, int f2, double *param, vector< vector<Vertex> > *seqA, vector< vector<Vertex> > *seqB){

#if DEBUG_GLUE
	printf("DEBUG TANGENZA\n");
	printf("Faccia 1\n");
	for(int h=0;h<(*mesh1)->face[f1].nVert;h++){
		printf("v: %g %g %g\n",(*mesh1)->vert[(*mesh1)->face[f1].vert[h]].x,(*mesh1)->vert[(*mesh1)->face[f1].vert[h]].y,(*mesh1)->vert[(*mesh1)->face[f1].vert[h]].z);
	}
	printf("Faccia 2\n");
	for(int h=0;h<(*mesh2)->face[f2].nVert;h++){
		printf("v: %g %g %g\n",(*mesh2)->vert[(*mesh2)->face[f2].vert[h]].x,(*mesh2)->vert[(*mesh2)->face[f2].vert[h]].y,(*mesh2)->vert[(*mesh2)->face[f2].vert[h]].z);
	}
#endif

	struct less_than_coord{
		inline bool operator() (const Vertex& v1, const Vertex& v2){
			return (v1.x < v2.x || v1.y<v2.y || v1.z<v2.z);
		}
	};

	vector<Vertex> pointQueue,chain,ch_tmp;
	int i,j,count1,count2,z1,z2; //,times;
	double d1,d2;
	Vertex p,p0,p1,p2,p3,tmp,b1,b2;
	Vector a,b,c,d;
	vector<Vertex> pIn2,pIn1; 		 		 /* mi dicono quali sono i punti di una faccia all'interno dell'altra */
	vector< vector<Vertex> > edge1,edge2;	 /* edge utilizzati per il calcolo delle intersezioni */
	vector< vector<Vertex> > seq0,seq1,seq2; /* sequenze di punti compresi tra due punti di intersezione tra le facce */
	vector< vector<Vertex> > inCh1,inCh2; 	 /* sequenze di punti interamente contenute in una faccia */
	vector<int> cnt((*mesh2)->face[f2].nVert);
	bool end,isIn,found;
	Vertex*	vert_tmp;

	seq0.clear();
	seq1.clear();
	seq2.clear();
	/* Test preliminare: verifico se vi sono lati sovrapposti */
	for(i=0;i<(*mesh1)->face[f1].nVert;i++){
		count1 = 0;
		p0.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[i]].x;
		p0.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[i]].y;
		p0.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[i]].z;
		p1.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[(i+1)%(*mesh1)->face[f1].nVert]].x;
		p1.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[(i+1)%(*mesh1)->face[f1].nVert]].y;
		p1.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[(i+1)%(*mesh1)->face[f1].nVert]].z;
		a.x = p0.x;
		a.y = p0.y;
		a.z = p0.z;
		b.x = p1.x;
		b.y = p1.y;
		b.z = p1.z;
		for(j=0;j<(*mesh2)->face[f2].nVert;j++){
			p2.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].x;
			p2.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].y;
			p2.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].z;
			p3.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[(j+1)%(*mesh2)->face[f2].nVert]].x;
			p3.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[(j+1)%(*mesh2)->face[f2].nVert]].y;
			p3.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[(j+1)%(*mesh2)->face[f2].nVert]].z;
			c.x = p2.x;
			c.y = p2.y;
			c.z = p2.z;
			d.x = p3.x;
			d.y = p3.y;
			d.z = p3.z;
			// printf("edge1 %g %g %g - %g %g %g edge2 %g %g %g - %g %g %g\n",p0.x,p0.y,p0.z,p1.x,p1.y,p1.z,p2.x,p2.y,p2.z,p3.x,p3.y,p3.z);
			// p0-p1 interamente contenuto o completamente sovrapposto a p2-p3
			if(gen_pointDsegment(p0,p2,p3,0.000002) && gen_pointDsegment(p1,p2,p3,0.000002)){
				printf("caso1\n");
				chain.push_back(p0);
				chain.push_back(p1);
				seq0.push_back(chain);
				chain.clear();
				// se non sono completamente sovrapposti,spezzo l'edge p2-p3
				if(!(gen_pointDsegment(p2,p0,p1,0.000002) && gen_pointDsegment(p3,p0,p1,0.000002))){
					if(p2.x < p0.x || p2.y < p0.y || p2.z < p0.z){    //lungo un edge varia una sola coordinata
						chain.push_back(p2);
						chain.push_back(p0);
						edge2.push_back(chain);
						chain.clear();
					}
					else if(p3.x < p0.x || p3.y < p0.y || p3.z < p0.z){
						chain.push_back(p0);
						chain.push_back(p3);
						edge2.push_back(chain);
						chain.clear();
					}
					if(p1.x < p3.x || p1.y < p3.y || p1.z < p3.z){
						chain.push_back(p1);
						chain.push_back(p3);
						edge2.push_back(chain);
						chain.clear();
					}
					else if(p1.x < p2.x || p1.y < p2.y || p1.z < p2.z){
						chain.push_back(p2);
						chain.push_back(p1);
						edge2.push_back(chain);
						chain.clear();
					}
				}
			}
			// p2-p3 interamente contenuto o completamente sovrapposto a p0-p1
			else if(gen_pointDsegment(p2,p0,p1,0.000002) && gen_pointDsegment(p3,p0,p1,0.000002)){
				printf("caso2\n");
				// se non sono completamente sovrapposti,spezzo l'edge
				if(!(gen_pointDsegment(p0,p2,p3,0.000002) && gen_pointDsegment(p1,p2,p3,0.000002))){
					chain.push_back(p2);
					chain.push_back(p3);
					seq0.push_back(chain);
					chain.clear();

					if(p0.x < p2.x || p0.y < p2.y || p0.z < p2.z){    //lungo un edge varia una sola coordinata
						chain.push_back(p0);
						chain.push_back(p2);
						edge1.push_back(chain);
						chain.clear();
					}
					else if(p1.x < p2.x || p1.y < p2.y || p1.z < p2.z){
						chain.push_back(p2);
						chain.push_back(p1);
						edge1.push_back(chain);
						chain.clear();
					}
					if(p3.x < p1.x || p3.y < p1.y || p3.z < p1.z){
						chain.push_back(p3);
						chain.push_back(p1);
						edge1.push_back(chain);
						chain.clear();
					}
					else if(p3.x < p0.x || p3.y < p0.y || p3.z < p0.z){
						chain.push_back(p0);
						chain.push_back(p3);
						edge1.push_back(chain);
						chain.clear();
					}
				}
			}
			// p2-p0-p3-p1
			else if(mat_pointDistance(a,d)>0.000002 && gen_pointDsegment(p0,p2,p3,0.000002) && gen_pointDsegment(p3,p0,p1,0.000002)){
				printf("caso3\n");
				chain.push_back(p0);
				chain.push_back(p3);
				seq0.push_back(chain);
				chain.clear();
				chain.push_back(p2);
				chain.push_back(p0);
				edge2.push_back(chain);
				chain.clear();
				chain.push_back(p3);
				chain.push_back(p1);
				edge1.push_back(chain);
				chain.clear();
			}
			// p3-p0-p2-p1
			else if(mat_pointDistance(a,c)>0.000002 && gen_pointDsegment(p0,p2,p3,0.000002) && gen_pointDsegment(p2,p0,p1,0.000002)){
				printf("caso4\n");
				chain.push_back(p0);
				chain.push_back(p2);
				seq0.push_back(chain);
				chain.clear();
				chain.push_back(p0);
				chain.push_back(p3);
				edge2.push_back(chain);
				chain.clear();
				chain.push_back(p2);
				chain.push_back(p1);
				edge1.push_back(chain);
				chain.clear();
			}
			// p0-p2-p1-p3
			else if(mat_pointDistance(b,c)>0.000002 && gen_pointDsegment(p1,p2,p3,0.000002) && gen_pointDsegment(p2,p0,p1,0.000002)){
				printf("caso5\n");
				chain.push_back(p2);
				chain.push_back(p1);
				seq0.push_back(chain);
				chain.clear();
				chain.push_back(p0);
				chain.push_back(p2);
				edge1.push_back(chain);
				chain.clear();
				chain.push_back(p1);
				chain.push_back(p3);
				edge2.push_back(chain);
				chain.clear();
			}
			// p0-p3-p1-p2
			else if(mat_pointDistance(b,d)>0.000002 && gen_pointDsegment(p1,p2,p3,0.000002) && gen_pointDsegment(p3,p0,p1,0.000002)){
				printf("caso6\n");
				chain.push_back(p3);
				chain.push_back(p1);
				seq0.push_back(chain);
				chain.clear();
				chain.push_back(p0);
				chain.push_back(p3);
				edge1.push_back(chain);
				chain.clear();
				chain.push_back(p2);
				chain.push_back(p1);
				edge2.push_back(chain);
				chain.clear();
			}
			else{
				// nessuna sovrapposizione
				// conto quante volte l'edge i non riscontra sovrapposizioni
				count1++;
				// se non si sovrappone a nessuno degli edge di f2, lo prendo così per com'è
				if(count1==(*mesh2)->face[f2].nVert){
					chain.push_back(p0);
					chain.push_back(p1);
					edge1.push_back(chain);
					chain.clear();
				}
				// conto quante volte l'edge j non riscontra sovrapposizioni
				cnt[j]++;
				// se non si sovrappone a nessuno degli edge di f1, lo prendo così per com'è
				if(cnt[j]==(*mesh1)->face[f1].nVert){
					chain.push_back(p2);
					chain.push_back(p3);
					edge2.push_back(chain);
					chain.clear();
				}
			}
		}
	}
#if DEBUG_GLUE
	printf("Edge non sovrapposti:\n");
	if(edge1.size()!=0)
		for(std::vector<double>::size_type g=0;g<edge1.size();g++)
			printf("e1-%d: %g %g %g - %g %g %g\n",g+1,edge1[g].at(0).x,edge1[g].at(0).y,edge1[g].at(0).z,edge1[g].at(1).x,edge1[g].at(1).y,edge1[g].at(1).z);
	if(edge2.size()!=0)
		for(std::vector<double>::size_type g=0;g<edge2.size();g++)
			printf("e2-%d: %g %g %g - %g %g %g\n",g+1,edge2[g].at(0).x,edge2[g].at(0).y,edge2[g].at(0).z,edge2[g].at(1).x,edge2[g].at(1).y,edge2[g].at(1).z);
#endif

	/* determino i punti di una faccia interni all'altra */
	for(j=0;j<(*mesh1)->face[f1].nVert;j++){
		p0.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[j]].x;
		p0.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[j]].y;
		p0.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[j]].z;
		if(gen_pointDplane2D(p0,*mesh2,f2,0.000002)){
			pIn2.push_back(p0);
		}
	}
	for(j=0;j<(*mesh2)->face[f2].nVert;j++){
		p2.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].x;
		p2.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].y;
		p2.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].z;
		if(gen_pointDplane2D(p2,*mesh1,f1,0.000002)){
			pIn1.push_back(p2);
		}
	}

	/* calcolo le intersezioni tra le due facce usando edge1 ed edge2 */
	if(edge1.size()!=0 && edge2.size()!=0){
		pointQueue = gen_setIntersect(edge1,edge2);
		// rimuovo i duplicati
		for(std::vector<double>::size_type t1=0;t1!=pointQueue.size();t1++){
			a.x = pointQueue[t1].x;
			a.y = pointQueue[t1].y;
			a.z = pointQueue[t1].z;
			for(std::vector<double>::size_type t2=t1+1;t2!=pointQueue.size();t2++){
				b.x = pointQueue[t2].x;
				b.y = pointQueue[t2].y;
				b.z = pointQueue[t2].z;
				if(a.x==b.x && a.y==b.y && a.z==b.z){
					pointQueue.erase(pointQueue.begin()+t2);
					t2--;
				}
			}
		}
		for(std::vector<double>::size_type t1=0;t1!=pointQueue.size();t1++){
			a.x = pointQueue[t1].x;
			a.y = pointQueue[t1].y;
			a.z = pointQueue[t1].z;
			printf("%g %g %g\n",a.x,a.y,a.z);
		}
	}
	chain.clear();
	/* Se non vi sono intersezioni e gli edge sono tutti sovrapposti marco le facce come tangenti */
	if(pointQueue.size()==0 && edge1.size()==0 && edge2.size()==0){
		(*mesh1)->face[f1].tan = 1;
		(*mesh2)->face[f2].tan = 1;
	}
	/* Se non vi sono intersezioni,controllo se una faccia è interna all'altra */
	else if(pointQueue.size()==0 && edge1.size()!=0 && edge2.size()!=0){
		// determino quale delle due facce è interna all'altra
		b1 = gen_faceCenter(*mesh1,f1);
		b2 = gen_faceCenter(*mesh2,f2);
		z1 = -1;
		z2 = -1;
		
		if(gen_faceInFace(*mesh1,f1,*mesh2,f2)==1){
			// f1 interna ad f2
			// cerco due punti di f1 e due punti di f2 (punti a minima distanza tra le due facce)
			p0 = (*mesh1)->vert[(*mesh1)->face[f1].vert[0]];
			p1 = (*mesh1)->vert[(*mesh1)->face[f1].vert[1]];
			p = (*mesh1)->vert[(*mesh1)->face[f1].vert[2]];
			printf("p0 %g %g %g - p1 %g %g %g\n",p0.x,p0.y,p0.z,p1.x,p1.y,p1.z);
			// prima trovo il punto di f2 più vicino a p0,con distanza da p1 maggiore della distanza da p0
			d1 = -1;
			d2 = -1;
			d.x = p0.x;
			d.y = p0.y;
			d.z = p0.z;
			a.x = p1.x;
			a.y = p1.y;
			a.z = p1.z;
			for(i=0;i<(*mesh2)->face[f2].nVert;i++){
				tmp = (*mesh2)->vert[(*mesh2)->face[f2].vert[i]];
				c.x = tmp.x;
				c.y = tmp.y;
				c.z = tmp.z;
				d1 = mat_pointDistance(c,d);
				if(d2==-1 || (d2>d1 && d1<mat_pointDistance(c,a))){
					p2 = tmp;
					z1 = i;
					d2 = d1;
				}
			}
			d1 = -1;
			d2 = -1;
			for(i=0;i<(*mesh2)->face[f2].nVert;i++){
				if(i==z1) continue;
				tmp = (*mesh2)->vert[(*mesh2)->face[f2].vert[i]];
				c.x = tmp.x;
				c.y = tmp.y;
				c.z = tmp.z;
				d.x = p1.x;
				d.y = p1.y;
				d.z = p1.z;
				d1 = mat_pointDistance(c,d);
				if(d2==-1 || d2>d1){
					p3 = tmp;
					z2 = i;
					d2 = d1;
				}
			}
			printf("p2 %g %g %g - p3 %g %g %g\n",p2.x,p2.y,p2.z,p3.x,p3.y,p3.z);
			// cerco un punto guida per la ricostruzione delle facce
			d1 = -1;
			d2 = -1;
			d.x = p.x;
			d.y = p.y;
			d.z = p.z;
			for(i=0;i<(*mesh2)->face[f2].nVert;i++){
				if(i==z1) continue;
				if(i==z2) continue;
				tmp = (*mesh2)->vert[(*mesh2)->face[f2].vert[i]];
				c.x = tmp.x;
				c.y = tmp.y;
				c.z = tmp.z;
				d1 = mat_pointDistance(c,d);
				if(d2==-1 || d2>d1){
					p = tmp;
					d1 = i;
				}
			}
			// aggiungo vertici di f1 a mesh2
			(*mesh2)->nVert = (*mesh2)->nVert+(*mesh1)->face[f1].nVert;		
			vert_tmp = (Vertex*)malloc(((*mesh2)->nVert+1) * sizeof(Vertex));
			if (!vert_tmp) ErrorMessage();
			// ... copia dei vertici e ... 
			for (i=1; i <= ((*mesh2)->nVert -(*mesh1)->face[f1].nVert); i++) {
				vert_tmp[i].x = (*mesh2)->vert[i].x;
				vert_tmp[i].y = (*mesh2)->vert[i].y;
				vert_tmp[i].z = (*mesh2)->vert[i].z;
				vert_tmp[i].tan = (*mesh2)->vert[i].tan;
				vert_tmp[i].ins = (*mesh2)->vert[i].ins;
			}
			// ... aggiunta nuovi vertici. 
			for(j=0;j<(*mesh1)->face[f1].nVert;j++){
					vert_tmp[i].x = (*mesh1)->vert[(*mesh1)->face[f1].vert[j]].x;
					vert_tmp[i].y = (*mesh1)->vert[(*mesh1)->face[f1].vert[j]].y;
					vert_tmp[i].z = (*mesh1)->vert[(*mesh1)->face[f1].vert[j]].z;
					vert_tmp[i].tan = 1;
					vert_tmp[i].ins = 0;
					i++;
			}		
			free((*mesh2)->vert);
			(*mesh2)->vert = vert_tmp;
			(*mesh2)->mod_LoadSubdivMesh();			
		
			// controllo se in f2 viene prima p2 o p3
			if(z1<z2){printf("z1 %d z2 %d\n",z1,z2);
				// p2 precede p3
				ch_tmp.clear();
				// inserisco le nuove facce in mesh2. 
				// Percorro f2 da p2,da li percorro le altre due facce fino ad arrivare a p3 e terminare il giro di f2.
				// aggiungo z1
				ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z1]]);
				printf("aggiunto %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// aggiungo p0
				ch_tmp.push_back(p0);
				printf("aggiunto p0 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// percorro f1 fino a p1
				for(j=(*mesh1)->face[f1].nVert-1;j>0;j--){
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[j]]);
					printf("aggiunto1 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				}
				// adesso aggiungo gli eventuali punti compresi tra p3(incluso) e p2
				// scelgo la direzione di movimento in base al punto guida
				if(d1>z1 && d1<z2){
					// da z2 a z1
					for(i=z2;i>z1;i--){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq2.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p2 e p3
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z1]]);
					for(i=z1-1;i>=0;i--){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					for(i=(*mesh2)->face[f2].nVert-1;i>z2;i--){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z2]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				else if(d1<z1 || d1>z2){
					// da z2 a nVert
					for(i=z2;i<(*mesh2)->face[f2].nVert;i++){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					// da 0 a z1-1
					for(i=0;i<z1;i++){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq2.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p2 e p3
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z1]]);
					for(i=z1+1;i<z2;i++){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z2]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				seq2.push_back(ch_tmp);
				ch_tmp.clear();				
			}
			else if(z1>z2){
				// p3 precede p2
				ch_tmp.clear();
				// inserisco le nuove facce in mesh2. 
				// Percorro f2 da p3,da li percorro le altre due facce fino ad arrivare a p2 e terminare il giro di f2.
				// aggiungo z2
				ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z2]]);
				printf("aggiunto %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// aggiungo p0
				ch_tmp.push_back(p0);
				printf("aggiunto p0 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// percorro f1 fino a p1
				for(j=(*mesh1)->face[f1].nVert-1;j>0;j--){
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[j]]);
					printf("aggiunto1 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				}
				// adesso aggiungo gli eventuali punti compresi tra p3(incluso) e p2
				// scelgo la direzione di movimento in base al punto guida
				if(d1>z2 && d1<z1){
					// da z1 a z2
					for(i=z1;i>z1;i--){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq2.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p3 e p2
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z2]]);
					for(i=z2-1;i>=0;i--){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					for(i=(*mesh2)->face[f2].nVert-1;i>z1;i--){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z1]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				else if(d1<z2 || d1>z1){
					// da z1 a nVert
					for(i=z1;i<(*mesh2)->face[f2].nVert;i++){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					// da 0 a z2-1
					for(i=0;i<z2;i++){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq2.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p3 e p2
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z2]]);
					for(i=z2+1;i<z1;i++){
						ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[z1]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				seq2.push_back(ch_tmp);
				ch_tmp.clear();
			}
			// la faccia di intersezione è data da f1
			chain.clear();
			for(j=0;j<(*mesh1)->face[f1].nVert;j++){
				chain.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[j]]);
			}					
		}
		else if(gen_faceInFace(*mesh1,f1,*mesh2,f2)==2){
			// f2 interna ad f1
			// cerco due punti di f1 e due punti di f2 (punti a minima distanza tra le due facce)
			p0 = (*mesh2)->vert[(*mesh2)->face[f2].vert[0]];
			p1 = (*mesh2)->vert[(*mesh2)->face[f2].vert[1]];
			p = (*mesh2)->vert[(*mesh2)->face[f2].vert[2]];
			printf("p0 %g %g %g - p1 %g %g %g\n",p0.x,p0.y,p0.z,p1.x,p1.y,p1.z);
			// prima trovo il punto di f1 più vicino a p0,con distanza da p1 maggiore della distanza da p0
			d1 = -1;
			d2 = -1;
			d.x = p0.x;
			d.y = p0.y;
			d.z = p0.z;
			a.x = p1.x;
			a.y = p1.y;
			a.z = p1.z;
			for(i=0;i<(*mesh1)->face[f1].nVert;i++){
				tmp = (*mesh1)->vert[(*mesh1)->face[f1].vert[i]];
				c.x = tmp.x;
				c.y = tmp.y;
				c.z = tmp.z;
				d1 = mat_pointDistance(c,d);
				if(d2==-1 || (d2>d1 && d1<mat_pointDistance(c,a))){
					p2 = tmp;
					z1 = i;
					d2 = d1;
				}
			}
			d1 = -1;
			d2 = -1;
			for(i=0;i<(*mesh1)->face[f1].nVert;i++){
				if(i==z1) continue;
				tmp = (*mesh1)->vert[(*mesh1)->face[f1].vert[i]];
				c.x = tmp.x;
				c.y = tmp.y;
				c.z = tmp.z;
				d.x = p1.x;
				d.y = p1.y;
				d.z = p1.z;
				d1 = mat_pointDistance(c,d);
				if(d2==-1 || d2>d1){
					p3 = tmp;
					z2 = i;
					d2 = d1;
				}
			}
			printf("p2 %g %g %g - p3 %g %g %g\n",p2.x,p2.y,p2.z,p3.x,p3.y,p3.z);
			// cerco un punto guida per la ricostruzione delle facce
			d1 = -1;
			d2 = -1;
			d.x = p.x;
			d.y = p.y;
			d.z = p.z;
			for(i=0;i<(*mesh1)->face[f1].nVert;i++){
				if(i==z1) continue;
				if(i==z2) continue;
				tmp = (*mesh1)->vert[(*mesh1)->face[f1].vert[i]];
				c.x = tmp.x;
				c.y = tmp.y;
				c.z = tmp.z;
				d1 = mat_pointDistance(c,d);
				if(d2==-1 || d2>d1){
					p = tmp;
					d1 = i;
				}
			}
			// aggiungo vertici di f2 a mesh1
			(*mesh1)->nVert = (*mesh1)->nVert+(*mesh2)->face[f2].nVert;		
			vert_tmp = (Vertex*)malloc(((*mesh1)->nVert+1) * sizeof(Vertex));
			if (!vert_tmp) ErrorMessage();
			// ... copia dei vertici e ... 
			for (i=1; i <= ((*mesh1)->nVert -(*mesh2)->face[f2].nVert); i++) {
				vert_tmp[i].x = (*mesh1)->vert[i].x;
				vert_tmp[i].y = (*mesh1)->vert[i].y;
				vert_tmp[i].z = (*mesh1)->vert[i].z;
				vert_tmp[i].tan = (*mesh1)->vert[i].tan;
				vert_tmp[i].ins = (*mesh1)->vert[i].ins;
			}
			// ... aggiunta nuovi vertici. 
			for(j=0;j<(*mesh2)->face[f2].nVert;j++){
				vert_tmp[i].x = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].x;
				vert_tmp[i].y = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].y;
				vert_tmp[i].z = (*mesh2)->vert[(*mesh2)->face[f2].vert[j]].z;
				vert_tmp[i].tan = 1;
				vert_tmp[i].ins = 0;
				i++;
			}		
			free((*mesh1)->vert);
			(*mesh1)->vert = vert_tmp;
			(*mesh1)->mod_LoadSubdivMesh();			
		
			// controllo se in f1 viene prima p2 o p3
			if(z1<z2){
				// p2 precede p3
				ch_tmp.clear();
				// inserisco le nuove facce in mesh1. 
				// Percorro f1 da p2,da li percorro le altre due facce fino ad arrivare a p3 e terminare il giro di f1.
				// aggiungo z1
				ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z1]]);
				printf("aggiunto %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// aggiungo p0
				ch_tmp.push_back(p0);
				printf("aggiunto p0 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// percorro f2 fino a p1
				for(j=(*mesh2)->face[f2].nVert-1;j>0;j--){
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[j]]);
					printf("aggiunto1 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				}
				// adesso aggiungo gli eventuali punti compresi tra p3(incluso) e p2
				// scelgo la direzione di movimento in base al punto guida
				if(d1>z1 && d1<z2){
					// da z2 a z1
					for(i=z2;i>z1;i--){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq1.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p2 e p3
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z1]]);
					for(i=z1-1;i>=0;i--){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					for(i=(*mesh1)->face[f1].nVert-1;i>z2;i--){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z2]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				else if(d1<z1 || d1>z2){
					// da z2 a nVert
					for(i=z2;i<(*mesh1)->face[f1].nVert;i++){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					// da 0 a z1-1
					for(i=0;i<z1;i++){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq1.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p2 e p3
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z1]]);
					for(i=z1+1;i<z2;i++){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z2]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				seq1.push_back(ch_tmp);
				ch_tmp.clear();				
			}
			else if(z1>z2){
				// p3 precede p2
				ch_tmp.clear();
				// inserisco le nuove facce in mesh1. 
				// Percorro f1 da p3,da li percorro le altre due facce fino ad arrivare a p2 e terminare il giro di f1.
				// aggiungo z2
				ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z2]]);
				printf("aggiunto %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// aggiungo p0
				ch_tmp.push_back(p0);
				printf("aggiunto p0 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				// percorro f2 fino a p1
				for(j=(*mesh2)->face[f2].nVert-1;j>0;j--){
					ch_tmp.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[j]]);
					printf("aggiunto1 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
				}
				// adesso aggiungo gli eventuali punti compresi tra p2(incluso) e p3
				// scelgo la direzione di movimento in base al punto guida
				if(d1>z2 && d1<z1){
					// da z1 a z2
					for(i=z1;i>z2;i--){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq1.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p3 e p2
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z2]]);
					for(i=z2-1;i>=0;i--){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					for(i=(*mesh1)->face[f1].nVert-1;i>z1;i--){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z1]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				else if(d1<z2 || d1>z1){
					// da z1 a nVert
					for(i=z1;i<(*mesh1)->face[f1].nVert;i++){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					// da 0 a z2-1
					for(i=0;i<z2;i++){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto2 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					seq1.push_back(ch_tmp);
					ch_tmp.clear();
					// un altra faccia è data dai 4 punti individuati prima e dagli eventuali tra p3 e p2
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z2]]);
					for(i=z2+1;i<z1;i++){
						ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[i]]);
						printf("aggiunto3 %g %g %g\n",ch_tmp[ch_tmp.size()-1].x,ch_tmp[ch_tmp.size()-1].y,ch_tmp[ch_tmp.size()-1].z);
					}
					ch_tmp.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[z1]]);
					ch_tmp.push_back(p1);
					ch_tmp.push_back(p0);
				}
				seq1.push_back(ch_tmp);
				ch_tmp.clear();
			}
			// la faccia di intersezione è data da f2
			chain.clear();
			for(j=0;j<(*mesh2)->face[f2].nVert;j++){
				chain.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[j]]);
			}								
		}
	}
	/* Se vi è una sola intersezione devo verificare se una delle facce è interamente contenuta nell'altra. */
	else if(pointQueue.size()==1){ // TODO tutta questa sezione è da fare!!!
		// inserisco il vertice di contatto tra le due facce nell'edge opportuno della faccia che non lo ha (se sovrapposizione su vertice, non aggiungo nulla)
		// determino quale delle due facce è interna all'altra
		Vertex b1 = gen_faceCenter(*mesh1,f1);
		Vertex b2 = gen_faceCenter(*mesh2,f2);
		if(gen_pointDplane(b1,param,*mesh2,f2,0.000002)){
			// f1 interna a f2
			// devo spezzare in due l'edge di f2 in cui si trova il punto di intersezione
			for(int s=0;s<(*mesh2)->face[f2].nVert;s++){
				p0.x=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[0]].x;
				p0.y=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[0]].y;
				p0.z=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[0]].z;
				p1.x=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[1]].x;
				p1.y=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[1]].y;
				p1.z=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[1]].z;
				if(gen_pointDsegment(pointQueue[0],p0,p1,0.000002)){
					gen_insPointOnEdge(mesh2,pointQueue[0],(*mesh2)->face[f2].edge[s]);
					// salvo gli estremi del segmento originale
					p2.x = p0.x;
					p2.y = p0.y;
					p2.z = p0.z;
					p3.x = p1.x;
					p3.y = p1.y;
					p3.z = p1.z;
				}
			}
			// salvo il punto di intersezione
			p0.x = pointQueue[0].x;
			p0.y = pointQueue[0].y;
			p0.z = pointQueue[0].z;
			// in chain devo mettere tutta f1
			// in seq2 devo mettere f2 con il ritaglio di f1
			chain.clear();
			ch_tmp.clear();
			vector<Vertex> e;
			vector< vector<Vertex> > e1,e2;
			for(int u=0;u<(*mesh1)->face[f1].nVert;u++){
				chain.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[u]]);
				// salvo il punto successivo al punto di intersezione in f1
				if(chain[chain.size()-1].x==p0.x && chain[chain.size()-1].y==p0.y && chain[chain.size()-1].z==p0.z){
					p1.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[(u+1)%(*mesh1)->face[f1].nVert]].x;
					p1.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[(u+1)%(*mesh1)->face[f1].nVert]].y;
					p1.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[(u+1)%(*mesh1)->face[f1].nVert]].z;
				}
				// salvo gli edge di f1 in un vector
				e.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[u]]);
				e.push_back((*mesh1)->vert[(*mesh1)->face[f1].vert[(u+1)%(*mesh1)->face[f1].nVert]]);
				e1.push_back(e);
				e.clear();
			}
			// p0 si trova tra p2 e p3,devo scegliere tra p2 e p3 di modo che il segmento p1-p* non attraversi f1
			// controllo intersezione di f1 con p1-p2
			e.push_back(p1);
			e.push_back(p2);
			e2.push_back(e);
			e.clear();
			e = gen_setIntersect(e1,e2);
			if(e.size()!=0 && e[0].x==p1.x && e[0].y==p1.y && e[0].z==p1.z){ // unica intersezione data da p1
				// una faccia è data dal triangolo p0-p1-p2
				e.clear();
				e.push_back(p0);
				e.push_back(p1);
				e.push_back(p2);
				seq2.push_back(e);

				// l'altra è data dai punti restanti di f2
				e.clear();
				// recupero l'indice di p2 in f2
				for(count2=0;count2<(*mesh2)->face[f2].nVert;count2++){
					tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
					tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
					tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
					if(tmp.x==p2.x && tmp.y==p2.y && tmp.z==p2.z){
						break;
					}
				}
				// controllo verso: se il punto successivo in f2 a p2 è p0,devo andare nel verso opposto
				if((*mesh2)->vert[(*mesh2)->face[f2].vert[(count2+1)%(*mesh2)->face[f2].nVert]].x==p0.x && (*mesh2)->vert[(*mesh2)->face[f2].vert[(count2+1)%(*mesh2)->face[f2].nVert]].y==p0.y && (*mesh2)->vert[(*mesh2)->face[f2].vert[(count2+1)%(*mesh2)->face[f2].nVert]].z==p0.z){
					// prima prendo i punti di f2
					for(;count2>=0;){
						tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
						tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
						tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
						// da p2 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2--;
						if(count2==-1)
							count2 = (*mesh2)->face[f2].nVert-1;
					}
				}
				else{
					// prima prendo i punti di f2
					for(;count2<(*mesh2)->face[f2].nVert;){
						tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
						tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
						tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
						// da p2 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2++;
						if(count2==(*mesh2)->face[f2].nVert)
							count2 = 0;
					}
				}
				// dopo prendo i punti di f1
				// recupero l'indice di p0 in f1
				for(count2=0;count2<(*mesh1)->face[f1].nVert;count2++){
					tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count1]].x;
					tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count1]].y;
					tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count1]].z;
					if(tmp.x==p0.x && tmp.y==p0.y && tmp.z==p0.z){
						break;
					}
				}
				// a ritroso, perchè p1 è il punto successivo a p0 in f1
				for(;count2>=0;){
					tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
					tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
					tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
					// da p0 a p1 (escluso)
					if(tmp.x!=p1.x && tmp.y!=p1.y && tmp.z!=p1.z){
						e.push_back(tmp);
					}
					else
						break;

					count2--;
					if(count2==-1)
						count2 = (*mesh1)->face[f1].nVert-1;
				}
				e.push_back(p1);
				seq2.push_back(e);
			}
			else{
				// una faccia è data dal triangolo p0-p1-p3
				e.clear();
				e.push_back(p0);
				e.push_back(p1);
				e.push_back(p3);
				seq2.push_back(e);

				// l'altra è data dai punti restanti di f2
				e.clear();
				// recupero l'indice di p3 in f2
				for(count2=0;count2<(*mesh2)->face[f2].nVert;count2++){
					tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
					tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
					tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
					if(tmp.x==p3.x && tmp.y==p3.y && tmp.z==p3.z){
						break;
					}
				}
				// controllo verso: se il punto successivo in f2 a p3 è p0,devo andare nel verso opposto
				if((*mesh2)->vert[(*mesh2)->face[f2].vert[(count2+1)%(*mesh2)->face[f2].nVert]].x==p0.x && (*mesh2)->vert[(*mesh2)->face[f2].vert[(count2+1)%(*mesh2)->face[f2].nVert]].y==p0.y && (*mesh2)->vert[(*mesh2)->face[f2].vert[(count2+1)%(*mesh2)->face[f2].nVert]].z==p0.z){
					// prima prendo i punti di f2
					for(;count2>=0;){
						tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
						tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
						tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
						// da p3 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2--;
						if(count2==-1)
							count2 = (*mesh2)->face[f2].nVert-1;
					}
				}
				else{
					// prima prendo i punti di f2
					for(;count2<(*mesh2)->face[f2].nVert;){
						tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
						tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
						tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
						// da p3 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2++;
						if(count2==(*mesh2)->face[f2].nVert)
							count2 = 0;
					}
				}
				// dopo prendo i punti di f1
				// recupero l'indice di p0 in f1
				for(count2=0;count2<(*mesh1)->face[f1].nVert;count2++){
					tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count1]].x;
					tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count1]].y;
					tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count1]].z;
					if(tmp.x==p0.x && tmp.y==p0.y && tmp.z==p0.z){
						break;
					}
				}
				// a ritroso, perchè p1 è il punto successivo a p0 in f1
				for(;count2>=0;){
					tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
					tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
					tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
					// da p0 a p1 (escluso)
					if(tmp.x!=p1.x && tmp.y!=p1.y && tmp.z!=p1.z){
						e.push_back(tmp);
					}
					else
						break;

					count2--;
					if(count2==-1)
						count2 = (*mesh1)->face[f1].nVert-1;
				}
			}
			e.push_back(p1);
			seq2.push_back(e);
		}
		else if(gen_pointDplane(b2,param,*mesh1,f1,0.000002)){
			// f2 interna a f1
			// devo spezzare in due l'edge di f1 in cui si trova il punto di intersezione
			for(int s=0;s<(*mesh1)->face[f1].nVert;s++){
				p0.x=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[0]].x;
				p0.y=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[0]].y;
				p0.z=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[0]].z;
				p1.x=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[1]].x;
				p1.y=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[1]].y;
				p1.z=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[1]].z;
				if(gen_pointDsegment(chain[0],p0,p1,0.000002)){
					gen_insPointOnEdge(mesh1,chain[0],(*mesh1)->face[f1].edge[s]);
					// salvo gli estremi del segmento originale
					p2.x = p0.x;
					p2.y = p0.y;
					p2.z = p0.z;
					p3.x = p1.x;
					p3.y = p1.y;
					p3.z = p1.z;
				}
			}
			// salvo il punto di intersezione
			p0.x = chain[0].x;
			p0.y = chain[0].y;
			p0.z = chain[0].z;
			// in chain devo mettere tutta f2
			// in seq1 devo mettere f1 con il ritaglio di f2
			chain.clear();
			ch_tmp.clear();
			vector<Vertex> e;
			vector< vector<Vertex> > e1,e2;
			for(int u=0;u<(*mesh2)->face[f2].nVert;u++){
				chain.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[u]]);
				// salvo il punto successivo al punto di intersezione in f2
				if(chain[chain.size()-1].x==p0.x && chain[chain.size()-1].y==p0.y && chain[chain.size()-1].z==p0.z){
					p1.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[(u+1)%(*mesh2)->face[f2].nVert]].x;
					p1.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[(u+1)%(*mesh2)->face[f2].nVert]].y;
					p1.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[(u+1)%(*mesh2)->face[f2].nVert]].z;
				}
				// salvo gli edge di f2 in un vector
				e.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[u]]);
				e.push_back((*mesh2)->vert[(*mesh2)->face[f2].vert[(u+1)%(*mesh2)->face[f2].nVert]]);
				e1.push_back(e);
				e.clear();
			}
			// p0 si trova tra p2 e p3,devo scegliere tra p2 e p3 di modo che il segmento p1-p* non attraversi f2
			// controllo intersezione di f2 con p1-p2
			e.push_back(p1);
			e.push_back(p2);
			e2.push_back(e);
			e.clear();
			e = gen_setIntersect(e1,e2);
			if(e.size()!=0 && e[0].x==p1.x && e[0].y==p1.y && e[0].z==p1.z){ // unica intersezione data da p1
				// una faccia è data dal triangolo p0-p1-p2
				e.clear();
				e.push_back(p0);
				e.push_back(p1);
				e.push_back(p2);
				seq1.push_back(e);

				// l'altra è data dai punti restanti di f1
				e.clear();
				// recupero l'indice di p2 in f1
				for(count2=0;count2<(*mesh1)->face[f1].nVert;count2++){
					tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
					tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
					tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
					if(tmp.x==p2.x && tmp.y==p2.y && tmp.z==p2.z){
						break;
					}
				}
				// controllo verso: se il punto successivo in f1 a p2 è p0,devo andare nel verso opposto
				if((*mesh1)->vert[(*mesh1)->face[f1].vert[(count2+1)%(*mesh1)->face[f1].nVert]].x==p0.x && (*mesh1)->vert[(*mesh1)->face[f1].vert[(count2+1)%(*mesh1)->face[f1].nVert]].y==p0.y && (*mesh1)->vert[(*mesh1)->face[f1].vert[(count2+1)%(*mesh1)->face[f1].nVert]].z==p0.z){
					// prima prendo i punti di f1
					for(;count2>=0;){
						tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
						tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
						tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
						// da p2 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2--;
						if(count2==-1)
							count2 = (*mesh1)->face[f1].nVert-1;
					}
				}
				else{
					// prima prendo i punti di f1
					for(;count2<(*mesh1)->face[f1].nVert;){
						tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
						tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
						tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
						// da p2 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2++;
						if(count2==(*mesh1)->face[f1].nVert)
							count2 = 0;
					}
				}
				// dopo prendo i punti di f2
				// recupero l'indice di p0 in f2
				for(count2=0;count2<(*mesh2)->face[f2].nVert;count2++){
					tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count1]].x;
					tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count1]].y;
					tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count1]].z;
					if(tmp.x==p0.x && tmp.y==p0.y && tmp.z==p0.z){
						break;
					}
				}
				// a ritroso, perchè p1 è il punto successivo a p0 in f2
				for(;count2>=0;){
					tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
					tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
					tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
					// da p0 a p1 (escluso)
					if(tmp.x!=p1.x && tmp.y!=p1.y && tmp.z!=p1.z){
						e.push_back(tmp);
					}
					else
						break;

					count2--;
					if(count2==-1)
						count2 = (*mesh2)->face[f2].nVert-1;
				}
				e.push_back(p1);
				seq1.push_back(e);
			}
			else{
				// una faccia è data dal triangolo p0-p1-p3
				e.clear();
				e.push_back(p0);
				e.push_back(p1);
				e.push_back(p3);
				seq1.push_back(e);

				// l'altra è data dai punti restanti di f1
				e.clear();
				// recupero l'indice di p3 in f1
				for(count2=0;count2<(*mesh1)->face[f1].nVert;count2++){
					tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
					tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
					tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
					if(tmp.x==p3.x && tmp.y==p3.y && tmp.z==p3.z){
						break;
					}
				}
				// controllo verso: se il punto successivo in f1 a p3 è p0,devo andare nel verso opposto
				if((*mesh1)->vert[(*mesh1)->face[f1].vert[(count2+1)%(*mesh1)->face[f1].nVert]].x==p0.x && (*mesh1)->vert[(*mesh1)->face[f1].vert[(count2+1)%(*mesh1)->face[f1].nVert]].y==p0.y && (*mesh1)->vert[(*mesh1)->face[f1].vert[(count2+1)%(*mesh1)->face[f1].nVert]].z==p0.z){
					// prima prendo i punti di f1
					for(;count2>=0;){
						tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
						tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
						tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
						// da p3 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2--;
						if(count2==-1)
							count2 = (*mesh1)->face[f1].nVert-1;
					}
				}
				else{
					// prima prendo i punti di f1
					for(;count2<(*mesh1)->face[f1].nVert;){
						tmp.x = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].x;
						tmp.y = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].y;
						tmp.z = (*mesh1)->vert[(*mesh1)->face[f1].vert[count2]].z;
						// da p3 a p0 (escluso)
						if(tmp.x!=p0.x && tmp.y!=p0.y && tmp.z!=p0.z){
							e.push_back(tmp);
						}
						else
							break;

						count2++;
						if(count2==(*mesh1)->face[f1].nVert)
							count2 = 0;
					}
				}
				// dopo prendo i punti di f2
				// recupero l'indice di p0 in f2
				for(count2=0;count2<(*mesh2)->face[f2].nVert;count2++){
					tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count1]].x;
					tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count1]].y;
					tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count1]].z;
					if(tmp.x==p0.x && tmp.y==p0.y && tmp.z==p0.z){
						break;
					}
				}
				// a ritroso, perchè p1 è il punto successivo a p0 in f2
				for(;count2>=0;){
					tmp.x = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].x;
					tmp.y = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].y;
					tmp.z = (*mesh2)->vert[(*mesh2)->face[f2].vert[count2]].z;
					// da p0 a p1 (escluso)
					if(tmp.x!=p1.x && tmp.y!=p1.y && tmp.z!=p1.z){
						e.push_back(tmp);
					}
					else
						break;

					count2--;
					if(count2==-1)
						count2 = (*mesh2)->face[f2].nVert-1;
				}
			}
			e.push_back(p1);
			seq1.push_back(e);
		}
	}	
	else if(pointQueue.size()>1){
		end = false;
		//times = 0;
		while(!end){
			/* Individuo le catene di punti comprese tra coppie di punti di intersezione. */
			for(std::vector<double>::size_type d=0;d<edge1.size();d++){

			/*	if(d==0)
					times++;
				if(times==3){
					end = true;
					break;
				}
			*/
				p0.x = edge1[d].at(0).x;
				p0.y = edge1[d].at(0).y;
				p0.z = edge1[d].at(0).z;
				p1.x = edge1[d].at(1).x;
				p1.y = edge1[d].at(1).y;
				p1.z = edge1[d].at(1).z;
				printf("Edge (%g %g %g) - (%g %g %g)  ",p0.x,p0.y,p0.z,p1.x,p1.y,p1.z);
				chain.clear();
				// prendo le intersezioni su questo edge (se non coincidono con gli estremi per il caso cubo1 cubo8)
				for(std::vector<double>::size_type y=0;y<pointQueue.size();y++){
					if(gen_pointDsegment(pointQueue[y],p0,p1,0.000002)/* &&
					   ((pointQueue[y].x!=p0.x || pointQueue[y].y!=p0.y || pointQueue[y].z!=p0.z) &&
					    (pointQueue[y].x!=p1.x || pointQueue[y].y!=p1.y || pointQueue[y].z!=p1.z))*/){
						chain.push_back(pointQueue[y]);
						printf(" Intersezione (%g %g %g)",pointQueue[y].x,pointQueue[y].y,pointQueue[y].z);
					}
				}
				printf("\n");
				if(chain.size()>=2){
					// ordino le intersezioni sull'edge
					Vertex temp;
					a.x = p0.x;
					a.y = p0.y;
					a.z = p0.z;
					for(std::vector<double>::size_type y=1;y<chain.size();y++) {
						for(std::vector<double>::size_type u=0;u<chain.size()-y;u++) {
							b.x = chain[u].x;
							b.y = chain[u].y;
							b.z = chain[u].z;
							c.x = chain[u+1].x;
							c.y = chain[u+1].y;
							c.z = chain[u+1].z;
							if(mat_pointDistance(a,b)>mat_pointDistance(a,c)){
								temp.x = chain[u+1].x;
								temp.y = chain[u+1].y;
								temp.z = chain[u+1].z;
								chain.erase(chain.begin()+u+1);
								chain.insert(chain.begin()+u,temp);
							}
						}
					}

					// completo la catena in corso aggiungendo l'ultimo punto
					if(ch_tmp.size()!=0){
						// controllo se devo prendere il primo o l'ultimo elemento di chain (vedo quale dei due punti è più vicino a p0)
						a.x = p0.x;
						a.y = p0.y;
						a.z = p0.z;
						b.x = chain[0].x;
						b.y = chain[0].y;
						b.z = chain[0].z;
						c.x = chain[chain.size()-1].x;
						c.y = chain[chain.size()-1].y;
						c.z = chain[chain.size()-1].z;
						if(mat_pointDistance(a,b)<mat_pointDistance(a,c)){
							if(chain[0].x!=p0.x || chain[0].y!=p0.y || chain[0].z!=p0.z){
								ch_tmp.push_back(chain[0]);
							}
							seq1.push_back(ch_tmp);
						}
						else{
							if(chain[chain.size()-1].x!=p0.x || chain[chain.size()-1].y!=p0.y || chain[chain.size()-1].z!=p0.z){
								ch_tmp.push_back(chain[chain.size()-1]);
							}
							seq1.push_back(ch_tmp);
						}

						// controllo se devo aggiungere catene da seq0
						if(seq0.size()!=0){
							for(std::vector<double>::size_type c=0;c<seq0.size();c++){
								if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
									ch_tmp.clear();
									seq1.push_back(seq0[c]);
								}
								else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
									ch_tmp.clear();
									ch_tmp.push_back(seq0[c].at(1));
									ch_tmp.push_back(seq0[c].at(0));
									seq1.push_back(ch_tmp);
								}
							}
						}

						ch_tmp.clear();
					}
					// printf("chain[0] %g %g %g \n",chain[0].x,chain[0].y,chain[0].z);
					// controllo se sono tornato al punto di partenza
					if(seq1.size()>0 && chain[0].x==seq1[0].at(0).x && chain[0].y==seq1[0].at(0).y && chain[0].z==seq1[0].at(0).z){
						end = true;
						break;
					}
					if(seq1.size()>0 && chain[0].x==seq1[0].at(seq1[0].size()-1).x && chain[0].y==seq1[0].at(seq1[0].size()-1).y && chain[0].z==seq1[0].at(seq1[0].size()-1).z){
						end = true;
						break;
					}
					// costruisco le catene,due punti alla volta
					// controllo se devo prendere il primo o l'ultimo elemento di chain (vedo quale dei due punti è l'ultimo inserito)
					while(chain.size()>=2){
						if(seq1.size()>0 && chain[0].x==seq1[seq1.size()-1].at(seq1[seq1.size()-1].size()-1).x && chain[0].y==seq1[seq1.size()-1].at(seq1[seq1.size()-1].size()-1).y && chain[0].z==seq1[seq1.size()-1].at(seq1[seq1.size()-1].size()-1).z ){
							ch_tmp.push_back(chain[0]);
							printf("Inserisco (%g %g %g)\n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
							ch_tmp.push_back(chain[1]);
							printf("Inserisco (%g %g %g)\n",ch_tmp[1].x,ch_tmp[1].y,ch_tmp[1].z);
							seq1.push_back(ch_tmp);
							chain.erase(chain.begin());

							// controllo se devo aggiungere catene da seq0
							if(seq0.size()!=0){
								for(std::vector<double>::size_type c=0;c<seq0.size();c++){
									if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										seq1.push_back(seq0[c]);
									}
									else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										ch_tmp.push_back(seq0[c].at(1));
										ch_tmp.push_back(seq0[c].at(0));
										seq1.push_back(ch_tmp);
									}
								}
							}

							ch_tmp.clear();
						}
						else if(seq1.size()>0 && chain[chain.size()-1].x==seq1[seq1.size()-1].at(seq1[seq1.size()-1].size()-1).x && chain[chain.size()-1].y==seq1[seq1.size()-1].at(seq1[seq1.size()-1].size()-1).y && chain[chain.size()-1].z==seq1[seq1.size()-1].at(seq1[seq1.size()-1].size()-1).z ){
							ch_tmp.push_back(chain[chain.size()-1]);
							printf("Inserisco (%g %g %g)\n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
							ch_tmp.push_back(chain[chain.size()-2]);
							printf("Inserisco (%g %g %g)\n",ch_tmp[1].x,ch_tmp[1].y,ch_tmp[1].z);
							seq1.push_back(ch_tmp);
							chain.erase(chain.end()-1);

							// controllo se devo aggiungere catene da seq0
							if(seq0.size()!=0){
								for(std::vector<double>::size_type c=0;c<seq0.size();c++){
									if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										seq1.push_back(seq0[c]);
									}
									else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										ch_tmp.push_back(seq0[c].at(1));
										ch_tmp.push_back(seq0[c].at(0));
										seq1.push_back(ch_tmp);
									}
								}
							}

							ch_tmp.clear();
						}
						else if(seq1.size()==0){
							// controllo se devo prendere il primo o l'ultimo elemento di chain (vedo quale dei due punti è più vicino a p0)
							a.x = p0.x;
							a.y = p0.y;
							a.z = p0.z;
							b.x = chain[0].x;
							b.y = chain[0].y;
							b.z = chain[0].z;
							c.x = chain[chain.size()-1].x;
							c.y = chain[chain.size()-1].y;
							c.z = chain[chain.size()-1].z;
							if(mat_pointDistance(a,b)<mat_pointDistance(a,c)){
								ch_tmp.push_back(chain[0]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
								ch_tmp.push_back(chain[1]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[1].x,ch_tmp[1].y,ch_tmp[1].z);
								chain.erase(chain.begin());
							}
							else{
								ch_tmp.push_back(chain[chain.size()-1]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
								ch_tmp.push_back(chain[chain.size()-2]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[1].x,ch_tmp[1].y,ch_tmp[1].z);
								chain.erase(chain.end()-1);
							}
							seq1.push_back(ch_tmp);

							// controllo se devo aggiungere catene da seq0
							if(seq0.size()!=0){
								for(std::vector<double>::size_type c=0;c<seq0.size();c++){
									if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										seq1.push_back(seq0[c]);
									}
									else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										ch_tmp.push_back(seq0[c].at(1));
										ch_tmp.push_back(seq0[c].at(0));
										seq1.push_back(ch_tmp);
									}
								}
							}

							ch_tmp.clear();
						}
					}
					if(chain.size()==1){
						// inizio la catena successiva
						ch_tmp.push_back(chain[0]);
						if(chain[0].x!=p1.x || chain[0].y!=p1.y || chain[0].z!=p1.z){
							ch_tmp.push_back(p1);
							printf("Inserisco (%g %g %g)\n",p1.x,p1.y,p1.z);
						}
					}
				}
				else if(chain.size()==1){
					// printf("ch_tmp[0] %g %g %g \n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
					if((chain[0].x!=p0.x || chain[0].y!=p0.y || chain[0].z!=p0.z)/* &&
					   (chain[0].x!=ch_tmp[0].x || chain[0].x!=ch_tmp[0].y || chain[0].x!=ch_tmp[0].z)*/){
						ch_tmp.push_back(chain[0]);
						printf("Inserisco (%g %g %g)\n",chain[0].x,chain[0].y,chain[0].z);
					}
					if(ch_tmp.size()>1){
						seq1.push_back(ch_tmp);
					}
					if(seq1.size()>0 && chain[0].x==seq1[0].at(0).x && chain[0].y==seq1[0].at(0).y && chain[0].z==seq1[0].at(0).z){
						end = true;
					}
					else{
						ch_tmp.clear();
						ch_tmp.push_back(chain[0]);
						if(chain[0].x!=p1.x || chain[0].y!=p1.y || chain[0].z!=p1.z){
							ch_tmp.push_back(p1);
							printf("Inserisco (%g %g %g)\n",p1.x,p1.y,p1.z);
						}
					}
				}
				else if(chain.size()==0){
					// inserisco p1 solo se sono in una catena (gli estremi di una catena devono essere punti di intersezione)
					if(ch_tmp.size()>0){
						ch_tmp.push_back(p1);
						printf("Inserisco (%g %g %g)\n",p1.x,p1.y,p1.z);
					}
				}

				// controllo se devo aggiungere catene da seq0
				if(seq0.size()!=0 && ch_tmp.size()!=0){
					for(std::vector<double>::size_type c=0;c<seq0.size();c++){
						if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
							seq1.push_back(ch_tmp);
							ch_tmp.clear();
							seq1.push_back(seq0[c]);
							ch_tmp.push_back(seq0[c].at(1));
						}
						else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
							seq1.push_back(ch_tmp);
							ch_tmp.clear();
							ch_tmp.push_back(seq0[c].at(1));
							ch_tmp.push_back(seq0[c].at(0));
							seq1.push_back(ch_tmp);
							ch_tmp.erase(ch_tmp.begin());
						}
					}
				}
				if(end == true) break;
			}
			if(end == true) break;
		}

#if DEBUG_GLUE
		if(seq1.size()>0) printf("Catene di punti per f1\n");
		for(std::vector<double>::size_type d=0;d<seq1.size();d++){
			printf("seq%d: ",d+1);
			for(std::vector<double>::size_type p=0;p<seq1[d].size();p++){
				printf("(%g %g %g) ",seq1[d].at(p).x,seq1[d].at(p).y,seq1[d].at(p).z);
			}
			printf("\n");
		}
		if(pIn2.size()>0) printf("Lista punti di f1 interni a f2\n");
		for(std::vector<double>::size_type s=0;s<pIn2.size();s++){
			printf("(%g %g %g) ",pIn2[s].x,pIn2[s].y,pIn2[s].z);
		}
		printf("\n");
#endif
		/* Ripeto per f2 */
		chain.clear();
		ch_tmp.clear();
		end = false;
		while(!end){
			for(std::vector<double>::size_type d=0;d<edge2.size();d++){
				// verifico che sia l'edge giusto (non ho ordine sequenziale tra gli edge in edge2)
				if(ch_tmp.size()!=0 && !(ch_tmp[ch_tmp.size()-1].x == edge2[d].at(0).x && ch_tmp[ch_tmp.size()-1].y == edge2[d].at(0).y && ch_tmp[ch_tmp.size()-1].z == edge2[d].at(0).z))
					continue;

				p0.x = edge2[d].at(0).x;
				p0.y = edge2[d].at(0).y;
				p0.z = edge2[d].at(0).z;
				p1.x = edge2[d].at(1).x;
				p1.y = edge2[d].at(1).y;
				p1.z = edge2[d].at(1).z;
				printf("Edge (%g %g %g) - (%g %g %g)  ",p0.x,p0.y,p0.z,p1.x,p1.y,p1.z);
				chain.clear();
				// prendo le intersezioni su questo edge
				for(std::vector<double>::size_type d=0;d<pointQueue.size();d++){
					if(gen_pointDsegment(pointQueue[d],p0,p1,0.000002)){
						chain.push_back(pointQueue[d]);
						printf(" Intersezione (%g %g %g)",pointQueue[d].x,pointQueue[d].y,pointQueue[d].z);
					}
				}
				printf("\n");
				if(chain.size()>=2){
					// ordino le intersezioni sull'edge
					Vertex temp;
					a.x = p0.x;
					a.y = p0.y;
					a.z = p0.z;
					for(std::vector<double>::size_type y=1;y<chain.size();y++) {
						for(std::vector<double>::size_type u=0;u<chain.size()-y;u++) {
							b.x = chain[u].x;
							b.y = chain[u].y;
							b.z = chain[u].z;
							c.x = chain[u+1].x;
							c.y = chain[u+1].y;
							c.z = chain[u+1].z;
							if(mat_pointDistance(a,b)>mat_pointDistance(a,c)){
								temp.x = chain[u+1].x;
								temp.y = chain[u+1].y;
								temp.z = chain[u+1].z;
								chain.erase(chain.begin()+u+1);
								chain.insert(chain.begin()+u,temp);
							}
						}
					}
					// completo la catena in corso aggiungendo l'ultimo punto
					if(ch_tmp.size()!=0){
						// controllo se devo prendere il primo o l'ultimo elemento di chain (vedo quale dei due punti è più vicino a p0)
						a.x = p0.x;
						a.y = p0.y;
						a.z = p0.z;
						b.x = chain[0].x;
						b.y = chain[0].y;
						b.z = chain[0].z;
						c.x = chain[chain.size()-1].x;
						c.y = chain[chain.size()-1].y;
						c.z = chain[chain.size()-1].z;
						if(mat_pointDistance(a,b)<mat_pointDistance(a,c)){
							if(chain[0].x!=p0.x || chain[0].y!=p0.y || chain[0].z!=p0.z){
								ch_tmp.push_back(chain[0]);
							}
								seq2.push_back(ch_tmp);
						}
						else{
							if(chain[0].x!=p0.x || chain[0].y!=p0.y || chain[0].z!=p0.z){
								ch_tmp.push_back(chain[chain.size()-1]);
							}
							seq2.push_back(ch_tmp);
						}

						// controllo se devo aggiungere catene da seq0
						if(seq0.size()!=0){
							for(std::vector<double>::size_type c=0;c<seq0.size();c++){
								if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
									ch_tmp.clear();
									seq2.push_back(seq0[c]);
								}
								else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
									ch_tmp.clear();
									ch_tmp.push_back(seq0[c].at(1));
									ch_tmp.push_back(seq0[c].at(0));
									seq2.push_back(ch_tmp);
								}
							}
						}

						ch_tmp.clear();
					}
					// controllo se sono tornato al punto di partenza
					if(seq2.size()>0 && chain[0].x==seq2[0].at(0).x && chain[0].y==seq2[0].at(0).y && chain[0].z==seq2[0].at(0).z){
						end = true;
						break;
					}
					if(seq2.size()>0 && chain[0].x==seq2[0].at(seq2[0].size()-1).x && chain[0].y==seq2[0].at(seq2[0].size()-1).y && chain[0].z==seq2[0].at(seq2[0].size()-1).z){
						end = true;
						break;
					}
					// costruisco le catene,due punti alla volta
					// controllo se devo prendere il primo o l'ultimo elemento di chain (vedo quale dei due punti è l'ultimo inserito)
					while(chain.size()>=2){
						if(seq2.size()>0 && chain[0].x==seq2[seq2.size()-1].at(seq2[seq2.size()-1].size()-1).x && chain[0].y==seq2[seq2.size()-1].at(seq2[seq2.size()-1].size()-1).y && chain[0].z==seq2[seq2.size()-1].at(seq2[seq2.size()-1].size()-1).z ){
							ch_tmp.push_back(chain[0]);
							ch_tmp.push_back(chain[1]);
							seq2.push_back(ch_tmp);
							chain.erase(chain.begin());

							// controllo se devo aggiungere catene da seq0
							if(seq0.size()!=0){
								for(std::vector<double>::size_type c=0;c<seq0.size();c++){
									if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										seq2.push_back(seq0[c]);
									}
									else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										ch_tmp.push_back(seq0[c].at(1));
										ch_tmp.push_back(seq0[c].at(0));
										seq2.push_back(ch_tmp);
									}
								}
							}

							ch_tmp.clear();
						}
						else if(seq2.size()>0 && chain[chain.size()-1].x==seq2[seq2.size()-1].at(seq2[seq2.size()-1].size()-1).x && chain[chain.size()-1].y==seq2[seq2.size()-1].at(seq2[seq2.size()-1].size()-1).y && chain[chain.size()-1].z==seq2[seq2.size()-1].at(seq2[seq2.size()-1].size()-1).z ){
							ch_tmp.push_back(chain[chain.size()-1]);
							ch_tmp.push_back(chain[chain.size()-2]);
							seq2.push_back(ch_tmp);
							chain.erase(chain.end()-1);

							// controllo se devo aggiungere catene da seq0
							if(seq0.size()!=0){
								for(std::vector<double>::size_type c=0;c<seq0.size();c++){
									if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										seq2.push_back(seq0[c]);
									}
									else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										ch_tmp.push_back(seq0[c].at(1));
										ch_tmp.push_back(seq0[c].at(0));
										seq2.push_back(ch_tmp);
									}
								}
							}

							ch_tmp.clear();

						}
						else if(seq2.size()==0){
							// controllo se devo prendere il primo o l'ultimo elemento di chain (vedo quale dei due punti è più vicino a p0)
							a.x = p0.x;
							a.y = p0.y;
							a.z = p0.z;
							b.x = chain[0].x;
							b.y = chain[0].y;
							b.z = chain[0].z;
							c.x = chain[chain.size()-1].x;
							c.y = chain[chain.size()-1].y;
							c.z = chain[chain.size()-1].z;
							if(mat_pointDistance(a,b)<mat_pointDistance(a,c)){
								ch_tmp.push_back(chain[0]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
								ch_tmp.push_back(chain[1]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[1].x,ch_tmp[1].y,ch_tmp[1].z);
								chain.erase(chain.begin());
							}
							else{
								ch_tmp.push_back(chain[chain.size()-1]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[0].x,ch_tmp[0].y,ch_tmp[0].z);
								ch_tmp.push_back(chain[chain.size()-2]);
								printf("Inserisco (%g %g %g)\n",ch_tmp[1].x,ch_tmp[1].y,ch_tmp[1].z);
								chain.erase(chain.end()-1);
							}
							seq2.push_back(ch_tmp);

							// controllo se devo aggiungere catene da seq0
							if(seq0.size()!=0){
								for(std::vector<double>::size_type c=0;c<seq0.size();c++){
									if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										seq2.push_back(seq0[c]);
									}
									else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
										ch_tmp.clear();
										ch_tmp.push_back(seq0[c].at(1));
										ch_tmp.push_back(seq0[c].at(0));
										seq2.push_back(ch_tmp);
									}
								}
							}

							ch_tmp.clear();
						}
					}
					if(chain.size()==1){
						// inizio la catena successiva
						ch_tmp.push_back(chain[0]);
						if(chain[0].x!=p1.x || chain[0].y!=p1.y || chain[0].z!=p1.z){
							ch_tmp.push_back(p1);
							printf("Inserisco (%g %g %g)\n",p1.x,p1.y,p1.z);
						}
					}
				}
				else if(chain.size()==1){
					if(chain[0].x!=p0.x || chain[0].y!=p0.y || chain[0].z!=p0.z){
						ch_tmp.push_back(chain[0]);
						printf("Inserisco (%g %g %g)\n",chain[0].x,chain[0].y,chain[0].z);
					}
					if(ch_tmp.size()>1){
						seq2.push_back(ch_tmp);
					}
					if(seq2.size()>0 && chain[0].x==seq2[0].at(0).x && chain[0].y==seq2[0].at(0).y && chain[0].z==seq2[0].at(0).z){
						end = true;
					}
					else{
						ch_tmp.clear();
						ch_tmp.push_back(chain[0]);
						if(chain[0].x!=p1.x || chain[0].y!=p1.y || chain[0].z!=p1.z){
							ch_tmp.push_back(p1);
							printf("Inserisco (%g %g %g)\n",p1.x,p1.y,p1.z);
						}
					}
				}
				else if(chain.size()==0){
					// inserisco p1 solo se sono in una catena (gli estremi di una catena devono essere punti di intersezione)
					if(ch_tmp.size()>0){
						ch_tmp.push_back(p1);
						printf("Inserisco (%g %g %g)\n",p1.x,p1.y,p1.z);
					}
				}

				// controllo se devo aggiungere catene da seq0
				if(seq0.size()!=0){
					for(std::vector<double>::size_type c=0;c<seq0.size();c++){
						if(seq0[c].at(0).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(0).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(0).z==ch_tmp[ch_tmp.size()-1].z){
							seq2.push_back(ch_tmp);
							ch_tmp.clear();
							seq2.push_back(seq0[c]);
							ch_tmp.push_back(seq0[c].at(1));
						}
						else if(seq0[c].at(1).x==ch_tmp[ch_tmp.size()-1].x && seq0[c].at(1).y==ch_tmp[ch_tmp.size()-1].y && seq0[c].at(1).z==ch_tmp[ch_tmp.size()-1].z){
							seq2.push_back(ch_tmp);
							ch_tmp.clear();
							ch_tmp.push_back(seq0[c].at(1));
							ch_tmp.push_back(seq0[c].at(0));
							seq2.push_back(ch_tmp);
							ch_tmp.erase(ch_tmp.begin());
						}
					}
				}
				if(end == true) break;
			}
			if(end == true) break;
		}
		printf("\n");
#if DEBUG_GLUE
		if(seq2.size()>0) printf("Catene di punti per f2\n");
		for(std::vector<double>::size_type d=0;d<seq2.size();d++){
			printf("seq%d: ",d+1);
			for(std::vector<double>::size_type p=0;p<seq2[d].size();p++){
				printf("(%g %g %g) ",seq2[d].at(p).x,seq2[d].at(p).y,seq2[d].at(p).z);
			}
			printf("\n");
		}
		if(pIn1.size()>0) printf("Lista punti di f2 interni a f1\n");
		for(std::vector<double>::size_type s=0;s<pIn1.size();s++){
			printf("(%g %g %g) ",pIn1[s].x,pIn1[s].y,pIn1[s].z);
		}
		printf("\n");
#endif

		/*
		 * Adesso ho la lista dei punti di intersezione tra gli edge delle due facce,
		 * le liste dei punti di ciascuna faccia interni all'altra faccia,
		 * le catene di punti che costituiscono i lati delle facce (seq1,seq2)
		 * (primo e ultimo punto di ogni catena sono punti di intersezione),
		 * i segmenti di sovrapposizione degli edge delle facce (seq0).
		 * Devo costruire la faccetta individuata dalla sovrapposizione.
		 */

		/* faccia di intersezione */
		chain.clear();
		// percorro le catene di f1 e decido di volta in volta se prendere la catena di f1 o la catena di f2
		// rimuovo le catene che utilizzo per la faccia di intersezione: le restanti catene saranno nuove facce
		for(std::vector<double>::size_type d=0;d<seq1.size();d++){
			count1=0;
			found = false;
			if(seq1[d].size()==2){
				// controllo se la catena di f2 è interna a f1
				for(std::vector<double>::size_type s=0;s<seq2.size();s++){
					if( seq2[s].at(0).x == seq1[d].at(0).x && seq2[s].at(0).y == seq1[d].at(0).y && seq2[s].at(0).z == seq1[d].at(0).z &&
						seq2[s].at(seq2[s].size()-1).x == seq1[d].at(1).x && seq2[s].at(seq2[s].size()-1).y == seq1[d].at(1).y && seq2[s].at(seq2[s].size()-1).z == seq1[d].at(1).z ){
						/* controllo se il secondo punto della catena sta nella lista dei punti interni a f1 */
						for(std::vector<double>::size_type c=0;c<pIn1.size();c++){
							if( seq2[s].at(1).x == pIn1[c].x &&
								seq2[s].at(1).y == pIn1[c].y &&
								seq2[s].at(1).z == pIn1[c].z ){

								count1 = 1;
								break;
							}
						}
						if(count1==1){
							// aggiungo la catena
							for(std::vector<double>::size_type v=0;v<seq2[s].size()-1;v++){
								chain.push_back(seq2[s].at(v));
								//printf("(%g %g %g) \n",chain[chain.size()-1].x,chain[chain.size()-1].y,chain[chain.size()-1].z);
							}
							inCh1.push_back(seq2[s]);
							seq2.erase(seq2.begin()+s);
							found = true;
						}
					}
					else if( seq2[s].at(0).x == seq1[d].at(1).x && seq2[s].at(0).y == seq1[d].at(1).y && seq2[s].at(0).z == seq1[d].at(1).z &&
							seq2[s].at(seq2[s].size()-1).x == seq1[d].at(0).x && seq2[s].at(seq2[s].size()-1).y == seq1[d].at(0).y && seq2[s].at(seq2[s].size()-1).z == seq1[d].at(0).z ){
						/* controllo se il secondo punto della catena sta nella lista dei punti interni a f1 */
						for(std::vector<double>::size_type c=0;c<pIn1.size();c++){
							if( seq2[s].at(1).x == pIn1[c].x &&
								seq2[s].at(1).y == pIn1[c].y &&
								seq2[s].at(1).z == pIn1[c].z ){

								count1 = 1;
								break;
							}
						}
						if(count1==1){
							// aggiungo la catena
							for(std::vector<int>::size_type v=seq2[s].size()-1;v>0;v--){
								chain.push_back(seq2[s].at(v));
								//printf("(%g %g %g) \n",chain[chain.size()-1].x,chain[chain.size()-1].y,chain[chain.size()-1].z);
							}
							inCh1.push_back(seq2[s]);
							seq2.erase(seq2.begin()+s);
							found = true;
						}
					}
					if(count1==1) break;
				}
				if(count1==0){
					/* singolo edge individuato da due punti di intersezione */
					chain.push_back(seq1[d].at(0));
					inCh2.push_back(seq1[d]);
					seq1.erase(seq1.begin()+d);
					d--;
					found = true;
					//printf("(%g %g %g) ",chain[chain.size()-1].x,chain[chain.size()-1].y,chain[chain.size()-1].z);
				}
			}
			else if(seq1[d].size()>2){
				/* controllo se il secondo punto della catena sta nella lista dei punti interni a f2 */
				for(std::vector<double>::size_type s=0;s<pIn2.size();s++){
					if( seq1[d].at(1).x == pIn2[s].x &&
						seq1[d].at(1).y == pIn2[s].y &&
						seq1[d].at(1).z == pIn2[s].z ){

						count1 = 1;
						break;
					}
				}
				if(count1==1){
					/* è una catena di punti interni a f2, aggiungo */
					for(std::vector<double>::size_type s=0;s<seq1[d].size()-1;s++)
						chain.push_back(seq1[d].at(s));
					inCh2.push_back(seq1[d]);
					seq1.erase(seq1.begin()+d);
					d--;
					found = true;
				}
				else{
					count1 = -1;
					count2 = -1;
					isIn = false;
					/* accedo a seq2 e cerco la catena da agganciare all'ultima catena aggiunta (catena con stesso punto iniziale e finale di seq1[d],con almeno un punto interno a f1) */
					for(std::vector<double>::size_type m=0;m<seq2.size();m++){
						for(std::vector<double>::size_type s=0;s<pIn1.size();s++){
							if( seq2[m].at(1).x == pIn1[s].x &&
								seq2[m].at(1).y == pIn1[s].y &&
								seq2[m].at(1).z == pIn1[s].z ){
								isIn = true;
								break;
							}
						}
						if( seq2[m].at(0).x == seq1[d].at(0).x &&
							seq2[m].at(0).y == seq1[d].at(0).y &&
							seq2[m].at(0).z == seq1[d].at(0).z &&
							seq2[m].at(seq2[m].size()-1).x == seq1[d].at(seq1[d].size()-1).x &&
							seq2[m].at(seq2[m].size()-1).y == seq1[d].at(seq1[d].size()-1).y &&
							seq2[m].at(seq2[m].size()-1).z == seq1[d].at(seq1[d].size()-1).z &&
							(isIn || seq2[m].size()==2 )){

							count1 = m;
							break;
						}
						else if(seq2[m].at(seq2[m].size()-1).x == seq1[d].at(0).x &&
								seq2[m].at(seq2[m].size()-1).y == seq1[d].at(0).y &&
								seq2[m].at(seq2[m].size()-1).z == seq1[d].at(0).z &&
								seq2[m].at(0).x == seq1[d].at(seq1[d].size()-1).x &&
								seq2[m].at(0).y == seq1[d].at(seq1[d].size()-1).y &&
								seq2[m].at(0).z == seq1[d].at(seq1[d].size()-1).z &&
								(isIn || seq2[m].size()==2)){

							count2 = m;
							break;
						}
					}
					/* Aggiungo la catena */
					if(count1!=-1){
						for(std::vector<double>::size_type s=0;s<seq2[count1].size()-1;s++){
							chain.push_back(seq2[count1].at(s));
							//printf("(%g %g %g) ",chain[chain.size()-1].x,chain[chain.size()-1].y,chain[chain.size()-1].z);
						}
						inCh1.push_back(seq2[count1]);
						seq2.erase(seq2.begin()+count1);
						found = true;
					}
					else if(count2!=-1){
						for(std::vector<double>::size_type s=seq2[count2].size()-1;s!=(std::vector<double>::size_type) 0;s--){
							chain.push_back(seq2[count2].at(s));
							//printf("(%g %g %g) ",chain[chain.size()-1].x,chain[chain.size()-1].y,chain[chain.size()-1].z);
						}
						inCh1.push_back(seq2[count2]);
						seq2.erase(seq2.begin()+count2);
						found = true;
					}
				}
			}
			/* Al momento non supporta la formazione di più facce di sovrapposizione
			 * a partire da due facce. Se non trovo un'altra catena,la catena stessa è una faccia. */
			if(!found){
				d--;
				chain.push_back(seq1[d].at(seq1[d].size()-1));
				seq1.erase(seq1.begin()+d);
				break;
			}
		}
#if DEBUG_GLUE
		printf("Vertici faccia di intersezione:\n");
		for(std::vector<double>::size_type d=0;d<chain.size();d++){
			printf("(%g %g %g) ",chain[d].x,chain[d].y,chain[d].z);
		}
		printf("\n");
#endif

		/* Adesso in chain ho la sequenza di vertici della faccia di intersezione.
		 * In seq1 e seq2 ho le catene di punti che appartengono alle altre facce,ottenute dai residui
		 * di f1 e f2.Devo aggiungere i punti necessari alla loro chiusura. */
		// per ogni sequenza,cerco in inCh* una catena di punti compresa tra i due estremi della sequenza
		for(std::vector<double>::size_type s=0;s<seq1.size();s++){
			p0 = seq1[s].at(0);
			p1 = seq1[s].at(seq1[s].size()-1);
			// cerco una catena compresa tra p0 e p1
			for(std::vector<double>::size_type c=0;c<inCh1.size();c++){
				if(inCh1[c].size()>2 && inCh1[c].at(0).x==p0.x && inCh1[c].at(0).y==p0.y && inCh1[c].at(0).z==p0.z &&
				   inCh1[c].at(inCh1[c].size()-1).x==p1.x && inCh1[c].at(inCh1[c].size()-1).y==p1.y && inCh1[c].at(inCh1[c].size()-1).z==p1.z){
					for(std::vector<double>::size_type b=inCh1[c].size()-2;b!=(std::vector<double>::size_type) 0;b--){
						seq1[s].push_back(inCh1[c].at(b));
					}
				}
				else if(inCh1[c].size()>2 && inCh1[c].at(0).x==p1.x && inCh1[c].at(0).y==p1.y && inCh1[c].at(0).z==p1.z &&
						inCh1[c].at(inCh1[c].size()-1).x==p0.x && inCh1[c].at(inCh1[c].size()-1).y==p0.y && inCh1[c].at(inCh1[c].size()-1).z==p0.z){
					for(std::vector<double>::size_type b=1;b<inCh1[c].size()-1;b++){
						seq1[s].push_back(inCh1[c].at(b));
					}
				}
			}
		}
		for(std::vector<double>::size_type s=0;s<seq2.size();s++){
			p0 = seq2[s].at(0);
			p1 = seq2[s].at(seq2[s].size()-1);
			// cerco una catena compresa tra p0 e p1
			for(std::vector<double>::size_type c=0;c<inCh2.size();c++){
				if(inCh2[c].size()>2 && inCh2[c].at(0).x==p0.x && inCh2[c].at(0).y==p0.y && inCh2[c].at(0).z==p0.z &&
						inCh2[c].at(inCh2[c].size()-1).x==p1.x && inCh2[c].at(inCh2[c].size()-1).y==p1.y && inCh2[c].at(inCh2[c].size()-1).z==p1.z){
					for(std::vector<double>::size_type b=inCh2[c].size()-2;b!=(std::vector<double>::size_type) 0;b--){
						seq2[s].push_back(inCh2[c].at(b));
					}
				}
				else if(inCh2[c].size()>2 && inCh2[c].at(0).x==p1.x && inCh2[c].at(0).y==p1.y && inCh2[c].at(0).z==p1.z &&
						inCh2[c].at(inCh2[c].size()-1).x==p0.x && inCh2[c].at(inCh2[c].size()-1).y==p0.y && inCh2[c].at(inCh2[c].size()-1).z==p0.z){
					for(std::vector<double>::size_type b=1;b<inCh2[c].size()-1;b++){
						seq2[s].push_back(inCh2[c].at(b));
					}
				}
			}
		}

#if DEBUG_GLUE
		printf("Vertici altre facce m1:\n");
		for(std::vector<double>::size_type d=0;d<seq1.size();d++){
			for(std::vector<double>::size_type s=0;s<seq1[d].size();s++){
				printf("(%g %g %g) ",seq1[d].at(s).x,seq1[d].at(s).y,seq1[d].at(s).z);
			}
			printf("\n");
		}
		printf("Vertici altre facce m2:\n");
		for(std::vector<double>::size_type d=0;d<seq2.size();d++){
			for(std::vector<double>::size_type s=0;s<seq2[d].size();s++){
				printf("(%g %g %g) ",seq2[d].at(s).x,seq2[d].at(s).y,seq2[d].at(s).z);
			}
			printf("\n");
		}
#endif

		// inserisco i punti di intersezione nelle facce
		for(std::vector<double>::size_type g=0;g!=pointQueue.size();g++){
			for(int s=0;s<(*mesh1)->face[f1].nVert;s++){
				p0.x=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[0]].x;
				p0.y=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[0]].y;
				p0.z=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[0]].z;
				p1.x=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[1]].x;
				p1.y=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[1]].y;
				p1.z=(*mesh1)->vert[(*mesh1)->edge[(*mesh1)->face[f1].edge[s]].vert[1]].z;
				if(gen_pointDsegment(pointQueue[g],p0,p1,0.000002)){
					gen_insPointOnEdge(mesh1,pointQueue[g],(*mesh1)->face[f1].edge[s]);
					break;
				}
			}
		}
		// Rimuovo dalla lista dei punti interni i punti già inseriti
		for(std::vector<double>::size_type g=0;g!=pIn1.size();g++){
			if((*mesh1)->mod_find_in_vert(pIn1[g])!=-1){
				pIn1.erase(pIn1.begin()+g);
				g--;
			}
		}
		/* Aggiungo alla mesh i vertici interni alle facce,mi serviranno dopo */
		count1 = (*mesh1)->nVert;
		(*mesh1)->nVert = ((*mesh1)->nVert)+pIn1.size();
		vert_tmp = (Vertex*)malloc(((*mesh1)->nVert+1) * sizeof(Vertex));
		if (!vert_tmp) ErrorMessage();
		/* ... copia dei vertici e ... */
		for (i=1; i <= count1; i++) {
			vert_tmp[i].x = (*mesh1)->vert[i].x;
			vert_tmp[i].y = (*mesh1)->vert[i].y;
			vert_tmp[i].z = (*mesh1)->vert[i].z;
			vert_tmp[i].tan = (*mesh1)->vert[i].tan;
			vert_tmp[i].ins = (*mesh1)->vert[i].ins;
		}
		/* ... aggiunta nuovi vertici. */
		for(std::vector<double>::size_type g=0;g!=pIn1.size();g++){
			vert_tmp[i].x = pIn1[g].x;
			vert_tmp[i].y = pIn1[g].y;
			vert_tmp[i].z = pIn1[g].z;
			vert_tmp[i].tan = 1;
			vert_tmp[i].ins = 0;
			i++;
		}		
		free((*mesh1)->vert);
		(*mesh1)->vert = vert_tmp;		
		(*mesh1)->mod_LoadSubdivMesh();

		// ripeto per mesh2
		for(std::vector<double>::size_type g=0;g!=pointQueue.size();g++){
			for(int s=0;s<(*mesh2)->face[f2].nVert;s++){
				p0.x=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[0]].x;
				p0.y=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[0]].y;
				p0.z=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[0]].z;
				p1.x=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[1]].x;
				p1.y=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[1]].y;
				p1.z=(*mesh2)->vert[(*mesh2)->edge[(*mesh2)->face[f2].edge[s]].vert[1]].z;
				if(gen_pointDsegment(pointQueue[g],p0,p1,0.000002)){
					gen_insPointOnEdge(mesh2,pointQueue[g],(*mesh2)->face[f2].edge[s]);
					break;
				}
			}
		}
		// Rimuovo dalla lista dei punti interni i punti già inseriti
		for(std::vector<double>::size_type g=0;g!=pIn2.size();g++){
			if((*mesh2)->mod_find_in_vert(pIn2[g])!=-1){
				pIn2.erase(pIn2.begin()+g);
				g--;
			}
		}
		/* Aggiungo alla mesh i vertici interni alle facce,mi serviranno dopo */
		count2 = (*mesh2)->nVert;
		(*mesh2)->nVert = ((*mesh2)->nVert)+pIn2.size();
		vert_tmp = (Vertex*)malloc(((*mesh2)->nVert+1) * sizeof(Vertex));
		if (!vert_tmp) ErrorMessage();
		/* ... copia dei vertici e ... */
		for (i=1; i <= count2; i++) {
			vert_tmp[i].x = (*mesh2)->vert[i].x;
			vert_tmp[i].y = (*mesh2)->vert[i].y;
			vert_tmp[i].z = (*mesh2)->vert[i].z;
			vert_tmp[i].tan = (*mesh2)->vert[i].tan;
			vert_tmp[i].ins = (*mesh2)->vert[i].ins;
		}
		/* ... aggiunta nuovi vertici. */
		for(std::vector<double>::size_type g=0;g!=pIn2.size();g++){
			vert_tmp[i].x = pIn2[g].x;
			vert_tmp[i].y = pIn2[g].y;
			vert_tmp[i].z = pIn2[g].z;
			vert_tmp[i].tan = 1;
			vert_tmp[i].ins = 0;
			i++;
		}
		free((*mesh2)->vert);
		(*mesh2)->vert = vert_tmp;
		(*mesh2)->mod_LoadSubdivMesh();

	}
	
	// copio seq1 e seq2 in seqA e seqB
	for(std::vector<double>::size_type s=0;s<seq1.size();s++){
		seqA->push_back(seq1[s]);
	}
	for(std::vector<double>::size_type s=0;s<seq2.size();s++){
		seqB->push_back(seq2[s]);
	}

	return chain;
}

// Individua le aree in tangenza tra due mesh,suddivide le facce esistenti,salva gli indici delle facce in tangenza
void gen_fTg(Mod_SubdivMesh **mesh1, Mod_SubdivMesh **mesh2){

	int count1,count2,face;
	bool test;
	vector<int> nf((*mesh1)->nFace +1);
	double param[4];
	vector<int> tmp;
	vector< vector<int> > tang;  // vector di vector di 5 elementi: f1,f2 e gli indici in profiles e faceChains*
	vector<Vertex> p;
	vector< vector<Vertex> > profiles;
	vector<vector< vector<Vertex> > > faceChainsA,faceChainsB;

	for(int i=1;i<=(*mesh1)->nFace;i++){
		(*mesh1)->face[i].tan = 0;
	}
	for(int j=1;j<=(*mesh2)->nFace;j++){
		(*mesh2)->face[j].tan = 0;
	}
	for(int i=1;i<=(*mesh1)->nEdge;i++){
		(*mesh1)->edge[i].tan = 0;
	}
	for(int j=1;j<=(*mesh2)->nEdge;j++){
		(*mesh2)->edge[j].tan = 0;
	}
	for(int i=1;i<=(*mesh1)->nVert;i++){
		(*mesh1)->vert[i].tan = 0;
		(*mesh1)->vert[i].ins = 0;
	}
	for(int j=1;j<=(*mesh2)->nVert;j++){
		(*mesh2)->vert[j].tan = 0;
		(*mesh2)->vert[j].ins = 0;
	}

	/*
	 * Effettuo il controllo tra le facce che appartengono
	 * alla regione di intersezione dei bounding box delle due mesh (confine incluso).
	 */
	for(int i=1;i<=(*mesh1)->nFace;i++){
		if((*mesh1)->face[i].bb==0) continue;
		// determino il piano della faccia i
		gen_complaneTest((*mesh1),i,param);
		for(int j=1;j<=(*mesh2)->nFace;j++){
			if((*mesh2)->face[j].bb==0) continue;
			vector< vector<Vertex> > seqA,seqB;
			// verifico se la faccia j è complanare alla faccia i
			if (gen_complaneFace(*mesh2,j,param)){
				// memorizzo le informazioni di tangenza
				p.clear();
				p = gen_faceOverlap(mesh1,mesh2,i,j,param,&seqA,&seqB);
				if(p.size()>0){
					tmp.clear();
					profiles.push_back(p);
					if(seqA.size()>0){
						faceChainsA.push_back(seqA);
						/*
						for(std::vector<double>::size_type t=0;t!=seqA.size();t++){
							printf("faccia %d\n",t);
							for(std::vector<double>::size_type r=0;r!=seqA[t].size();r++){
								printf("%g %g %g \n",seqA[t].at(r).x,seqA[t].at(r).y,seqA[t].at(r).z);
							}
						}
						*/
					}
					if(seqB.size()>0){
						faceChainsB.push_back(seqB);
						/*
						for(std::vector<double>::size_type t=0;t!=seqB.size();t++){
							printf("faccia %d\n",t);
							for(std::vector<double>::size_type r=0;r!=seqB[t].size();r++){
								printf("%g %g %g \n",seqB[t].at(r).x,seqB[t].at(r).y,seqB[t].at(r).z);
							}
						}
						*/
					}
					tmp.push_back(i);
					tmp.push_back(j);
					tmp.push_back(profiles.size()-1);
					tmp.push_back(faceChainsA.size()-1);
					tmp.push_back(faceChainsB.size()-1);
					tang.push_back(tmp);
				}
			}
		}
	}

	for(std::vector<double>::size_type t=0;t!=nf.size();t++)
		nf[t] = 0;

	/* Inserisco i profili di sovrapposizione,marco le nuove facce che corrispondono alla zona di tangenza. */
	for(std::vector<double>::size_type d=0;d<tang.size();d++){
		face = tang[d].at(0);
		// se ho già operato su questa faccia,devo vedere su quale delle nuove facce operare
		if(nf[tang[d].at(0)]!=0){
			count1 = 0;
			count2 = 0;
			test = true;
			while(count1!=nf[tang[d].at(0)]){
				printf("esamino faccia %d + %d\n",face,count2);
				if((*mesh1)->face[face+count2].tan!=1){
					printf("la faccia %d + %d non è tangente\n",face,count2);
					count1++;
					// verifico che tutti i punti della faccia di intersezione appartengano alla faccia
					for(std::vector<double>::size_type t=0;t!=profiles[tang[d].at(2)].size();t++){
						if(!gen_pnpoly(*mesh1,face+count2,profiles[tang[d].at(2)].at(t))){
							test = false;
							printf("il punto %g %g %g non appartiene alla faccia\n",profiles[tang[d].at(2)].at(t).x,profiles[tang[d].at(2)].at(t).y,profiles[tang[d].at(2)].at(t).z);
							break;
						}
					}
					if(test) break;
				}
				count2++;
			}
			face = face + count2;
		}
		printf("pos:%d \n",tang[d].at(3));
		printf("mesh 1 face %d\n",face);
		gen_insertTanProfile(*mesh1,face,profiles[tang[d].at(2)],faceChainsA,tang[d].at(3),nf[tang[d].at(0)]);
		// aggiorno il numero di facce non tangenti presenti nella faccia originale
		if(nf[tang[d].at(0)]==0 && tang[d].at(3)!=-1) nf[tang[d].at(0)] = faceChainsA[tang[d].at(3)].size();
		/* Ho suddiviso una faccia in m facce. Quindi ho m-1 facce in più.
		 * Tutti gli elementi in tang che riferiscono una faccia di indice maggiore alla faccia i
		 * devono essere incrementati. */
		for(std::vector<double>::size_type g=d;g<tang.size();g++){
			if(tang[g].at(0)>tang[d].at(0) && tang[d].at(3)!=-1){
				if(nf[tang[d].at(0)]==0)
					tang[g].at(0) = tang[g].at(0)+faceChainsA[tang[d].at(3)].size();
				else
					tang[g].at(0) = tang[g].at(0)+1;
			}
		}
		/* Marco la faccia i come interessata dalla tangenza */
		(*mesh1)->face[face].tan = 1;
		/* Marco gli edge della faccia i come interessati dalla tangenza */
		for(int v=0;v<(*mesh1)->face[face].nVert;v++){
			(*mesh1)->edge[(*mesh1)->face[face].edge[v]].tan = 1;
		}
		/* Marco i punti della faccia i come interessati dalla tangenza */
		for(int v=0;v<(*mesh1)->face[face].nVert;v++){
			(*mesh1)->vert[(*mesh1)->face[face].vert[v]].tan = 1;
		}
	}	

	// mi assicuro che per ogni faccia con punti tangenti questi siano il primo e gli ultimi
	count1 = -1;
	for(int i=1;i<=(*mesh1)->nFace;i++){
		// in posizione 0 devo avere un punto tan e in posizione 1 un punto non tan
		vector<int> tmp((*mesh1)->face[i].nVert);
		for (int j=0;j<(*mesh1)->face[i].nVert;j++){
			tmp[j] = (*mesh1)->face[i].vert[j];
			if((*mesh1)->vert[(*mesh1)->face[i].vert[j]].tan==1 && (*mesh1)->vert[(*mesh1)->face[i].vert[(j+1)%(*mesh1)->face[i].nVert]].tan!=1)
				count1 = j;
		}
		if(count1>0){
			for (int j=0;j<(*mesh1)->face[i].nVert;j++)
				// printf("debug1 ord %d\n",tmp[j]);
			for (int j=0;j<(*mesh1)->face[i].nVert; j++){
				// devono scorrere tutti i punti di una quantità pari a count1
				(*mesh1)->face[i].vert[j] = tmp[(j+count1)%(*mesh1)->face[i].nVert];
				// printf("debug2 ord %d\n",(*mesh1)->face[i].vert[j]);
			}
		}
	}

	for(std::vector<double>::size_type t=0;t!=nf.size();t++)
		nf[t] = 0;

	/* ripeto per mesh2 */
	for(std::vector<double>::size_type d=0;d<tang.size();d++){
		face = tang[d].at(1);
		// se ho già operato su questa faccia,devo vedere su quale delle nuove facce operare
		if(nf[tang[d].at(1)]!=0){
			count1 = 0;
			count2 = 0;
			test = true;
			while(count1!=nf[tang[d].at(1)]){
				if((*mesh2)->face[face+count2].tan!=1){
					count1++;
					// verifico che tutti i punti della faccia di intersezione appartengano alla faccia
					for(std::vector<double>::size_type t=0;t!=profiles[tang[d].at(2)].size();t++){
						if(!gen_pnpoly(*mesh2,face+count2,profiles[tang[d].at(2)].at(t))){
							test = false;
							break;
						}
					}
					if(test) break;
				}
				count2++;
			}
			face = face + count2;
		}
		printf("mesh 2 face %d\n",face);
		gen_insertTanProfile(*mesh2,face,profiles[tang[d].at(2)],faceChainsB,tang[d].at(4),nf[tang[d].at(1)]);
		// aggiorno il numero di facce non tangenti presenti nella faccia originale
		if(nf[tang[d].at(1)]==0 && tang[d].at(4)!=-1) nf[tang[d].at(1)] = faceChainsB[tang[d].at(4)].size();
		/* Ho suddiviso una faccia, in chains.size() +1 facce. Quindi ho chains.size() facce in più.
		 * Tutti gli elementi in tang che riferiscono una faccia di indice maggiore alla faccia i
		 * devono essere incrementati. */
		for(std::vector<double>::size_type g=d;g<tang.size();g++){
			if(tang[g].at(1)>tang[d].at(1) && tang[d].at(4)!=-1){
				if(nf[tang[d].at(1)]==0)
					tang[g].at(1) = tang[g].at(1)+faceChainsB[tang[d].at(4)].size();
				else
					tang[g].at(1) = tang[g].at(1)+1;
			}
		}
		/* Marco la faccia j come interessata dalla tangenza */
		(*mesh2)->face[tang[d].at(1)].tan = 1;
		/* Marco gli edge interessati dalla tangenza */
		for(int v=0;v<(*mesh2)->face[tang[d].at(1)].nVert;v++){
			(*mesh2)->edge[(*mesh2)->face[tang[d].at(1)].edge[v]].tan = 1;
		}
		/* Marco i punti della faccia j come interessati dalla tangenza */
		for(int v=0;v<(*mesh2)->face[tang[d].at(1)].nVert;v++){
			(*mesh2)->vert[(*mesh2)->face[tang[d].at(1)].vert[v]].tan = 1;
		}
	}

	// mi assicuro che per ogni faccia con punti tangenti questi siano il primo e gli ultimi
	count1 = -1;
	for(int i=1;i<=(*mesh2)->nFace;i++){
		// in posizione 0 devo avere un punto tan e in posizione 1 un punto non tan
		vector<int> tmp((*mesh2)->face[i].nVert);
		for (int j=0;j<(*mesh2)->face[i].nVert;j++){
			tmp[j] = (*mesh2)->face[i].vert[j];
			if((*mesh2)->vert[(*mesh2)->face[i].vert[j]].tan==1 && (*mesh2)->vert[(*mesh2)->face[i].vert[(j+1)%(*mesh2)->face[i].nVert]].tan!=1)
				count1 = j;
			// printf("debug1 ord %d\n",tmp[j]);
		}
		if(count1>0){
			for (int j=0;j<(*mesh2)->face[i].nVert; j++){
				// devono scorrere tutti i punti di una quantità pari a count1
				(*mesh2)->face[i].vert[j] = tmp[(j+count1)%(*mesh2)->face[i].nVert];
				// printf("debug2 ord %d\n",(*mesh2)->face[i].vert[j]);
			}
		}
	}
	
	(*mesh1)->mod_LoadSubdivMesh();
	(*mesh2)->mod_LoadSubdivMesh();

#if DEBUG_GLUE
	printf("Facce in tangenza m1:\n");
	for(int v=1;v<=(*mesh1)->nFace;v++){
		printf("%d ",(*mesh1)->face[v].tan);
	}
	printf("\n");
	for(int v=1;v<=(*mesh1)->nFace;v++){
		if((*mesh1)->face[v].tan == 1){
			for(int x=0;x<(*mesh1)->face[v].nVert;x++){
				if((*mesh1)->vert[(*mesh1)->face[v].vert[x]].tan == 1){
					printf("(%g %g %g)",(*mesh1)->vert[(*mesh1)->face[v].vert[x]].x,(*mesh1)->vert[(*mesh1)->face[v].vert[x]].y,(*mesh1)->vert[(*mesh1)->face[v].vert[x]].z);
				}
			}
			printf("\n");
		}
	}
	printf("Facce in tangenza m2:\n");
	for(int v=1;v<=(*mesh2)->nFace;v++){
		printf("%d ",(*mesh2)->face[v].tan);
	}
	printf("\n");
	for(int v=1;v<=(*mesh2)->nFace;v++){
		if((*mesh2)->face[v].tan == 1){
			for(int x=0;x<(*mesh2)->face[v].nVert;x++){
				if((*mesh2)->vert[(*mesh2)->face[v].vert[x]].tan == 1){
					printf("(%g %g %g)",(*mesh2)->vert[(*mesh2)->face[v].vert[x]].x,(*mesh2)->vert[(*mesh2)->face[v].vert[x]].y,(*mesh2)->vert[(*mesh2)->face[v].vert[x]].z);
				}
			}
			printf("\n");
		}
	}
#endif


	return;
}

// Inserisce un profilo di tangenza in una faccia
void gen_insertTanProfile(Mod_SubdivMesh *mesh, int f, vector<Vertex> profile, vector< vector< vector<Vertex> > > faceChains, int index, int flag){

	Vertex p0,p1,p2,p3;
	Face *faces,*tmp;
	int nf,m,test,test2,ix1,ix2,ip1,ip2,i1,i2,p;
	vector<Vertex> c,fc;
	vector< vector<Vertex> > chains;

	/* In profile ho una faccia, in chains le altre.
	 * Se chains ha size pari a zero, non devo far nulla (sovrapposizione totale della faccia f) */
	if(index!=-1){
		chains = faceChains[index];
		m = 1;
		test = 0;
		test2 = 0;
		if(flag==0)		
			nf = mesh->nFace+chains.size();
		else if(flag!=0)
			nf = mesh->nFace+1;
		faces = (Face*)malloc((nf+1)*sizeof(Face));  // (vecchie facce -1) + faccia in tangenza + residui +1
		for(int i=1;i<=mesh->nFace;i++){
			if(i!=f){
				// copio la faccia
				faces[m].nVert = mesh->face[i].nVert;
				faces[m].pointInto = mesh->face[i].pointInto;
				faces[m].tan = mesh->face[i].tan;
				faces[m].bb = mesh->face[i].bb;

				for (int j=0;j<faces[m].nVert;j++)
					faces[m].vert[j] = mesh->face[i].vert[j];

				m++;
			}
			else{
				// inserisco le nuove facce
				// prima la faccia che individua la sovrapposizione
				faces[m].nVert = profile.size();
				faces[m].pointInto = 0;
				faces[m].bb = 1;
				// Per mantenere coerenti le normali,basta confrontare l'orientamento
				// partendo da un edge pre-esistente e seguire quel verso.
				for(int v=0;v<mesh->face[f].nVert;v++){
					// prendo un edge della faccia originale
					p0.x = mesh->vert[mesh->face[f].vert[v]].x;
					p0.y = mesh->vert[mesh->face[f].vert[v]].y;
					p0.z = mesh->vert[mesh->face[f].vert[v]].z;
					p1.x = mesh->vert[mesh->face[f].vert[(v+1) % mesh->face[f].nVert]].x;
					p1.y = mesh->vert[mesh->face[f].vert[(v+1) % mesh->face[f].nVert]].y;
					p1.z = mesh->vert[mesh->face[f].vert[(v+1) % mesh->face[f].nVert]].z;
					// verifico se appartiene al profilo
					test = 0;
					for(std::vector<double>::size_type d=0;d<profile.size();d++){
						if( p0.x==profile[d].x && p0.y==profile[d].y && p0.z==profile[d].z &&
							p1.x==profile[(d+1)%profile.size()].x && p1.y==profile[(d+1)%profile.size()].y && p1.z==profile[(d+1)%profile.size()].z ){
							// il verso del profilo è corretto
							test = 1;
							break;
						}
						else if(p1.x==profile[d].x && p1.y==profile[d].y && p1.z==profile[d].z &&
								p0.x==profile[(d+1)%profile.size()].x && p0.y==profile[(d+1)%profile.size()].y && p0.z==profile[(d+1)%profile.size()].z){
							//il verso del profilo è inverso
							test = -1;
							break;
						}
					}
					if(test!=0) break;
				}
				if(test==1){
					for (std::vector<double>::size_type j=0;j<profile.size();j++){
						faces[m].vert[j] = mesh->mod_find_in_vert(profile[j]);
					}
				}
				else if(test==-1){
					i1 = 0;
					for (std::vector<double>::size_type j=profile.size()-1;j!=(std::vector<double>::size_type) -1;j--){
						faces[m].vert[i1] = mesh->mod_find_in_vert(profile[j]);
						i1++;
					}
				}
				// se test=0 la faccia di intersezione è totalmente interna alla faccia della mesh,
				// prima creo le altre facce,poi inserisco profile
				if(test==0) 
					test2 = m;				
				m++;
				if(test!=0){
					printf("DEBUG1  Faccia di intersezione\n");
					for(int v=0;v<faces[m-1].nVert;v++){
						printf("%g %g %g\n",mesh->vert[faces[m-1].vert[v]].x,mesh->vert[faces[m-1].vert[v]].y,mesh->vert[faces[m-1].vert[v]].z);
					}
					printf("\n");
				}

				// se flag!=0 devo creare solo un altra faccia, con il residuo della faccia originale. Altrimenti devo inserire tutte le altre facce.
				if(flag!=0){

					// aggiungo alla faccia originale i punti sugli edge (in un vector)
					for(int v=0;v<mesh->face[f].nVert;v++){
						p0 = mesh->vert[mesh->face[f].vert[v]];
						fc.push_back(p0);
						p1 = mesh->vert[mesh->face[f].vert[(v+1)%mesh->face[f].nVert]];
						for(std::vector<double>::size_type b=0;b!=profile.size();b++){
							ip1 = mesh->mod_find_in_vert(profile[b]);
							ip1 = mesh->mod_find_in_face(mesh->face,f,ip1);
							if(ip1==mesh->face[f].nVert && gen_pointDsegment(profile[b],p0,p1,0.000002)){
								fc.push_back(profile[b]);
							}
						}
					}
					printf("face con punti su edge: ");
					for(std::vector<double>::size_type d=0;d!=fc.size();d++){
						p0 = fc[d];
						printf("(%g %g %g) ",p0.x,p0.y,p0.z);
					}
					printf("\n");

					// cerco un punto precedente a un punto che non appartiene alla faccia originale
					i1 = -1;
					for(std::vector<double>::size_type d=0;d!=profile.size()-1;d++){
						p0 = profile[d];
						p1 = profile[d+1];
						ip1 = -1;
						ix1 = -1;
						for(std::vector<double>::size_type a=0;a!=fc.size();a++){
							if(ip1==-1 && fc[a].x==p0.x && fc[a].y==p0.y && fc[a].z==p0.z){
								ip1 = d;
							}
							if(ix1==-1 && fc[a].x==p1.x && fc[a].y==p1.y && fc[a].z==p1.z){
								ix1 = d+1;
							}
						}
						if(ip1!=-1 && ix1==-1){
							i1 = d;
							break;
						}
						else if(d==profile.size()-2 && ip1!=-1 && ix1!=-1){
							i1 = profile.size()-1;
							break;
						}
					}
					// cerco un punto successivo a un punto che non appartiene alla faccia originale
					i2 = -1;
					for(std::vector<double>::size_type d=0;d!=profile.size()-1;d++){
						p0 = profile[d];
						p1 = profile[d+1];
						ip2 = -1;
						ix2 = -1;
						for(std::vector<double>::size_type a=0;a!=fc.size();a++){
							if(ip2==-1 && fc[a].x==p0.x && fc[a].y==p0.y && fc[a].z==p0.z){
								ip2 = d;
							}
							if(ix2==-1 && fc[a].x==p1.x && fc[a].y==p1.y && fc[a].z==p1.z){
								ix2 = d+1;
							}
						}
						if(ip2==-1 && ix2!=-1){
							i2 = d+1;
							break;
						}
						else if(d==profile.size()-2 && ip2==-1 && ix2==-1){
							i2 = 0;
							break;
						}
					}
					if(i1==-1 || i2==-1){
						printf("ho due punti da collegare\n");
						// non ci sono punti che non appartengono alla faccia originale
						// devo trovare i due punti della faccia di intersezione che hanno
						// creato un nuovo edge,e inserirlo nella faccia originale modificando il percorso
						// verifico il successivo del profilo e aggiungo se non è il successivo di fc
						// altrimenti devo prendere il precedente del profilo
						ip1 = -1;
						// se il verso del profilo è inverso, lo inverto per comodità. poi lo devo invertire di nuovo.
						if(test==-1){
							printf("profile: ");
							for(std::vector<double>::size_type d=0;d!=profile.size();d++){
								p0 = profile[d];
								printf("(%g %g %g) ",p0.x,p0.y,p0.z);
							}
							printf("\n");
							std::reverse(profile.begin(), profile.end());
							printf("profile invertito: ");
							for(std::vector<double>::size_type d=0;d!=profile.size();d++){
								p0 = profile[d];
								printf("(%g %g %g) ",p0.x,p0.y,p0.z);
							}
							printf("\n");
						}
						for(std::vector<double>::size_type a=0;a!=fc.size();a++){
							p0 = fc[a];
							p1 = fc[(a+1)%fc.size()];
							// se il verso del profilo è corretto
							for(std::vector<double>::size_type b=0;b!=profile.size();b++){
								p2 = profile[b];
								p3 = profile[(b+1)%profile.size()];
								if((p0.x==p2.x && p0.y==p2.y && p0.z==p2.z)&&(p1.x!=p3.x || p1.y!=p3.y || p1.z!=p3.z)){
									// se i punti successivi non combaciano, ho trovato la chiusura
									for(std::vector<double>::size_type c=0;c!=fc.size();c++){
										if(fc[c].x==p3.x && fc[c].y==p3.y && fc[c].z==p3.z){
											printf("punto1 %g %g %g\n",p3.x,p3.y,p3.z);
											printf("punto2 %g %g %g\n",p2.x,p2.y,p2.z);
											c=(c+1)%fc.size();
											while(fc[c].x!=p2.x || fc[c].y!=p2.y || fc[c].z!=p2.z){
												printf("punto %g %g %g\n",fc[c].x,fc[c].y,fc[c].z);
												fc.erase(fc.begin()+c);

											}
											ip1 = 1;
											break;
										}
									}
								}
								if(ip1==1) break;
							}
							if(ip1==1) break;
						}
						if(test==-1){
							std::reverse(profile.begin(), profile.end());
						}
						// adesso posso creare la faccia, se non combacia con la faccia di intersezione
						// verifico che residuo e faccia originale non coincidano (controllo estremi)
						p = 0;
						if( mesh->mod_find_in_vert(profile[0]) == mesh->mod_find_in_vert(fc[0]) &&
							mesh->mod_find_in_vert(profile[profile.size()-1]) == mesh->mod_find_in_vert(fc[fc.size()-1]))
								p = 1;
						if(p==0){
							faces[m].pointInto = 0;
							faces[m].tan = 0;
							faces[m].bb = 1;
							p = 0;
							for(std::vector<double>::size_type d=0;d!=fc.size();d++){
								faces[m].vert[p] = mesh->mod_find_in_vert(fc[d]);
								p++;
							}
							faces[m].nVert = p;
							printf("DEBUG TANPROFILE\n");
							for(int v=0;v<faces[m].nVert;v++){
								printf("%g %g %g\n",mesh->vert[faces[m].vert[v]].x,mesh->vert[faces[m].vert[v]].y,mesh->vert[faces[m].vert[v]].z);
							}
							printf("\n");
							m++;
						}
						else{
							nf--;
							tmp = (Face*)malloc((nf+1)*sizeof(Face));
							// ricopio tutte le facce precedenti
							for(int i=1;i<m;i++){
								// copio la faccia
								tmp[i].nVert = faces[i].nVert;
								tmp[i].pointInto = faces[i].pointInto;
								tmp[i].bb = faces[i].bb;
								tmp[i].tan = faces[i].tan;
								for (int j=0;j<tmp[i].nVert;j++)
									tmp[i].vert[j] = faces[i].vert[j];
							}
							free(faces);
							faces = tmp;
						}
					}
					else{
						printf("i1 %g %g %g\n",profile[i1].x,profile[i1].y,profile[i1].z);
						printf("i2 %g %g %g\n",profile[i2].x,profile[i2].y,profile[i2].z);
						/* Adesso ho:
						 * - i1 -> indice in profile di un estremo della catena dei nuovi punti
						 * - i2 -> indice in profile di un estremo della catena dei nuovi punti
						 * Salvo in un vettore la catena dei nuovi punti.
						 */
						for(std::vector<double>::size_type d=i1+1;d!=(std::vector<double>::size_type) i2;d++){
							if(d>profile.size()-1)
								break;
							c.push_back(profile[d]);
						}
						if(i2<i1){
							for(std::vector<double>::size_type d=0;d!=(std::vector<double>::size_type) i2;d++){
								c.push_back(profile[d]);
							}
						}

						// percorro fc e mi fermo appena trovo i1 o i2 in profile
						ip1 = 0;
						for(std::vector<double>::size_type a=0;a!=fc.size();a++){
							if((fc[a].x==profile[i1].x && fc[a].y==profile[i1].y && fc[a].z==profile[i1].z)||
									(fc[a].x==profile[i2].x && fc[a].y==profile[i2].y && fc[a].z==profile[i2].z)){
								printf("trovato ip1 %g %g %g\n",fc[a].x,fc[a].y,fc[a].z);
								break;
							}
							ip1++;
						}
						// percorro fc e mi fermo appena trovo i1 o i2 in profile (l'altro punto)
						ip2 = ip1+1;
						for(std::vector<double>::size_type a=(std::vector<double>::size_type) ip1+1;a!=fc.size();a++){
							if((fc[a].x==profile[i1].x && fc[a].y==profile[i1].y && fc[a].z==profile[i1].z)||(fc[a].x==profile[i2].x && fc[a].y==profile[i2].y && fc[a].z==profile[i2].z)){
								printf("trovato ip2 %g %g %g\n",fc[a].x,fc[a].y,fc[a].z);
								break;
							}
							ip2++;
						}

						// adesso posso creare la faccia
						faces[m].pointInto = 0;
						faces[m].bb = 1;
						faces[m].tan = 0;
						faces[m].vert[0] = -1;
						p = 0;
						for(std::vector<double>::size_type v=0;v!=fc.size();v++){
							printf("prendo punto %g %g %g\n",fc[v].x,fc[v].y,fc[v].z);
							faces[m].vert[p] = mesh->mod_find_in_vert(fc[v]);
							p++;
							ix1 = v;
							if(ix1==ip1){
								// se il verso del profilo è corretto
								if(test == 1){
									// aggiungo alla faccia i nuovi punti della catena del profilo in senso inverso
									for(std::vector<int>::size_type d=c.size()-1;d!=(std::vector<int>::size_type) -1;d--){
										faces[m].vert[p] = mesh->mod_find_in_vert(c[d]);
										printf("prendo punto da i2 %g %g %g\n",c[d].x,c[d].y,c[d].z);
										p++;
									}
									// aggiungo ip2
									faces[m].vert[p] = mesh->mod_find_in_vert(fc[ip2]);
									printf("prendo punto i1  %g %g %g\n",fc[ip2].x,fc[ip2].y,fc[ip2].z);
									p++;
									v = ip2;
								}
								// se il verso del profilo è inverso
								else if(test == -1){
									// aggiungo alla faccia i nuovi punti della catena del profilo
									for(std::vector<double>::size_type d=0;d!=c.size();d++){
										faces[m].vert[p] = mesh->mod_find_in_vert(c[d]);
										printf("prendo punto da i1 %g %g %g\n",c[d].x,c[d].y,c[d].z);
										p++;
									}
									// aggiungo ip2
									faces[m].vert[p] = mesh->mod_find_in_vert(fc[ip2]);
									printf("prendo punto i2  %g %g %g\n",fc[ip2].x,fc[ip2].y,fc[ip2].z);
									p++;
									v = ip2;
								}
							}
						}
						faces[m].nVert = p;
						printf("DEBUG TANPROFILE\n");
						for(int v=0;v<faces[m].nVert;v++){
							printf("%g %g %g\n",mesh->vert[faces[m].vert[v]].x,mesh->vert[faces[m].vert[v]].y,mesh->vert[faces[m].vert[v]].z);
						}
						printf("\n");
						m++;
					}
				}
				else{
					printf("chains size %d\n",chains.size());
					for(std::vector<int>::size_type v=0;v!=chains.size();v++){
						printf("chain %d\n",v);
						for(std::vector<int>::size_type z=0;z!=chains[v].size();z++)
							printf("%g %g %g\n",chains[v].at(z).x,chains[v].at(z).y,chains[v].at(z).z);
						printf("\n");
					}
					// adesso tutte le altre facce
					for(std::vector<double>::size_type v=0;v<chains.size();v++){
						faces[m].nVert = chains[v].size();
						faces[m].pointInto = 0;
						faces[m].bb = 1;
						faces[m].tan = 0;
						// Per mantenere coerenti le normali,basta confrontare l'orientamento
						// partendo da un edge pre-esistente e seguire quel verso.
						for(int z=0;z<mesh->face[f].nVert;z++){
							// prendo un edge della faccia originale
							p0.x = mesh->vert[mesh->face[f].vert[z]].x;
							p0.y = mesh->vert[mesh->face[f].vert[z]].y;
							p0.z = mesh->vert[mesh->face[f].vert[z]].z;
							p1.x = mesh->vert[mesh->face[f].vert[(z+1) % mesh->face[f].nVert]].x;
							p1.y = mesh->vert[mesh->face[f].vert[(z+1) % mesh->face[f].nVert]].y;
							p1.z = mesh->vert[mesh->face[f].vert[(z+1) % mesh->face[f].nVert]].z;
							// verifico se appartiene al profilo
							test = 0;
							for(std::vector<double>::size_type d=0;d!=chains[v].size();d++){
								if( p0.x==chains[v].at(d).x && p0.y==chains[v].at(d).y && p0.z==chains[v].at(d).z &&
									p1.x==chains[v].at((d+1)%chains[v].size()).x && p1.y==chains[v].at((d+1)%chains[v].size()).y && p1.z==chains[v].at((d+1)%chains[v].size()).z ){
									// il verso del profilo è corretto
									test = 1;
									break;
								}
								else if(p1.x==chains[v].at(d).x && p1.y==chains[v].at(d).y && p1.z==chains[v].at(d).z &&
										p0.x==chains[v].at((d+1)%chains[v].size()).x && p0.y==chains[v].at((d+1)%chains[v].size()).y && p0.z==chains[v].at((d+1)%chains[v].size()).z){
										//il verso del profilo è inverso
										test = -1;
										break;
								}
							}
							if(test!=0) break;
						}
						if(test==1){
							for (std::vector<double>::size_type j=0;j!=chains[v].size();j++){
								faces[m].vert[j] = mesh->mod_find_in_vert(chains[v].at(j));
								// printf("debug %d\n",faces[m].vert[j]);
							}
						}
						else if(test==-1){
							for (std::vector<double>::size_type j=chains[v].size()-1;j!=(std::vector<double>::size_type) -1;j--){
								faces[m].vert[j] = mesh->mod_find_in_vert(chains[v].at(j));
								// printf("debug %d\n",faces[m].vert[j]);
							}
						}
						m++;
						printf("DEBUG CHAINPROFILE\n");
						for(int v=0;v<faces[m-1].nVert;v++){
							printf("%g %g %g\n",mesh->vert[faces[m-1].vert[v]].x,mesh->vert[faces[m-1].vert[v]].y,mesh->vert[faces[m-1].vert[v]].z);
						}
						printf("\n");
					}
					// se profile era totalmente interna la inserisco adesso. Per mantenere coerenti le normali
					// devo cercare un edge di contatto con una delle ultime facce inserite
					if(test2!=0){
						faces[test2].nVert = profile.size();
						faces[test2].pointInto = 0;
						faces[test2].bb = 1;
						// Per mantenere coerenti le normali,basta confrontare l'orientamento
						// partendo da un edge pre-esistente e seguire quel verso.
						// Guardo gli edge delle chains.size() facce successive a test2
						for(std::vector<int>::size_type y=0;y!=chains.size();y++){
							for(int v=0;v<faces[test2+y+1].nVert;v++){
								// prendo un edge della faccia
								p0.x = mesh->vert[faces[test2+y+1].vert[v]].x;
								p0.y = mesh->vert[faces[test2+y+1].vert[v]].y;
								p0.z = mesh->vert[faces[test2+y+1].vert[v]].z;
								p1.x = mesh->vert[faces[test2+y+1].vert[(v+1) % faces[test2+y+1].nVert]].x;
								p1.y = mesh->vert[faces[test2+y+1].vert[(v+1) % faces[test2+y+1].nVert]].y;
								p1.z = mesh->vert[faces[test2+y+1].vert[(v+1) % faces[test2+y+1].nVert]].z;
								// verifico se appartiene al profilo
								test = 0;
								for(std::vector<double>::size_type d=0;d<profile.size();d++){
									if( p0.x==profile[d].x && p0.y==profile[d].y && p0.z==profile[d].z &&
											p1.x==profile[(d+1)%profile.size()].x && p1.y==profile[(d+1)%profile.size()].y && p1.z==profile[(d+1)%profile.size()].z ){
										// il verso del profilo è corretto
										test = 1;
										break;
									}
									else if(p1.x==profile[d].x && p1.y==profile[d].y && p1.z==profile[d].z &&
											p0.x==profile[(d+1)%profile.size()].x && p0.y==profile[(d+1)%profile.size()].y && p0.z==profile[(d+1)%profile.size()].z){
										//il verso del profilo è inverso
										test = -1;
										break;
									}
								}
								if(test!=0) break;
							}
							if(test==-1){
								for (std::vector<double>::size_type j=0;j<profile.size();j++){
									faces[test2].vert[j] = mesh->mod_find_in_vert(profile[j]);
								}
								break;
							}
							else if(test==1){
								i1 = 0;
								for (std::vector<double>::size_type j=profile.size()-1;j!=(std::vector<double>::size_type) -1;j--){
									faces[test2].vert[i1] = mesh->mod_find_in_vert(profile[j]);
									i1++;
								}
								break;
							}
						}
						printf("DEBUG2 Faccia di intersezione\n");
						for(int v=0;v<faces[test2].nVert;v++){
							printf("%g %g %g\n",mesh->vert[faces[test2].vert[v]].x,mesh->vert[faces[test2].vert[v]].y,mesh->vert[faces[test2].vert[v]].z);
						}
						printf("\n");
					}
				}
			}
		}
		free(mesh->face);
		free(mesh->edge);
		mesh->nFace = nf;
		mesh->face = faces;
		mesh->mod_LoadSubdivMesh();
	}

	return;
}

/* Inserisce un punto in un edge,spezzandolo in due, l'inserimento nella faccia è sempre in posizione 0
 * spostando in posizione finale il vertice 0 (necessario per la gestione del profilo di tangenza) */
void gen_insPointOnEdge(Mod_SubdivMesh **mesh, Vertex v, int edge){

	int i,j,p,q;
	Vertex *vert_tmp;
	Face *face_tmp;

	// se il vertice è un estremo dell'edge non devo far nulla
	i = (*mesh)->mod_find_in_vert(v);
	p = i;
	if(i!=-1 && (i==(*mesh)->edge[edge].vert[0] || i==(*mesh)->edge[edge].vert[1])){
		return;
	}
	
	(*mesh)->nVert = ((*mesh)->nVert)+1;
	vert_tmp = (Vertex*)malloc(((*mesh)->nVert+1) * sizeof(Vertex));
	if (!vert_tmp) ErrorMessage();
	face_tmp = (Face*)malloc(((*mesh)->nFace+1) * sizeof(Face));
	if (!face_tmp) ErrorMessage();

	/* ... copia dei vertici e ... */
	for (i=1; i < (*mesh)->nVert; i++) {
		vert_tmp[i].x = (*mesh)->vert[i].x;
		vert_tmp[i].y = (*mesh)->vert[i].y;
		vert_tmp[i].z = (*mesh)->vert[i].z;
		vert_tmp[i].tan = (*mesh)->vert[i].tan;	
		vert_tmp[i].ins = (*mesh)->vert[i].ins;		
	}
	/* ... aggiunta nuovo vertice (se non già presente) e ... */
	if(p==-1){
		vert_tmp[i].x = v.x;
		vert_tmp[i].y = v.y;
		vert_tmp[i].z = v.z;
		
		vert_tmp[i].ins = 1;

		p = i;
	}
	
	/* ... copia delle faccette. */
	for (i=1; i <= (*mesh)->nFace; i++) {

		// controllo se sono in una faccia a cui devo aggiungere il nuovo vertice
		if( i == (*mesh)->edge[edge].neigh[0] || i == (*mesh)->edge[edge].neigh[1] ){

			face_tmp[i].nVert = ((*mesh)->face[i].nVert)+1;
			face_tmp[i].pointInto = (*mesh)->face[i].pointInto;
			face_tmp[i].tan = (*mesh)->face[i].tan;
			face_tmp[i].bb = (*mesh)->face[i].bb;

			q = 0;
			for (j=0; j < (*mesh)->face[i].nVert; j++){
				if((*mesh)->face[i].edge[j] == edge){
					face_tmp[i].vert[q] = (*mesh)->face[i].vert[j];
					q++;
					face_tmp[i].vert[q] = p;
				}
				else
					face_tmp[i].vert[q] = (*mesh)->face[i].vert[j];
				q++;
			}

		}
		else{
			face_tmp[i].nVert = (*mesh)->face[i].nVert;
			face_tmp[i].pointInto = (*mesh)->face[i].pointInto;
			face_tmp[i].tan = (*mesh)->face[i].tan;
			face_tmp[i].bb = (*mesh)->face[i].bb;

			for (j=0; j < face_tmp[i].nVert; j++)
				face_tmp[i].vert[j] = (*mesh)->face[i].vert[j];
		}
	}

	free((*mesh)->vert);
	free((*mesh)->face);
	(*mesh)->vert = vert_tmp;
	(*mesh)->face = face_tmp;
	(*mesh)->mod_LoadSubdivMesh();

	return;
}

/* Dati due insiemi di edge complanari, ne calcola le intersezioni. */
vector<Vertex> gen_setIntersect(vector< vector<Vertex> > edge1, vector< vector<Vertex> > edge2){

	int coord;
	double num,den,t;
	Vertex p0,p1,p2,p3,tmp;
	vector<Vertex> pointQueue;

	/* piano in cui mi trovo */
	if(edge1[0].at(0).x == edge1[0].at(1).x) coord = 1;
	else if(edge1[0].at(0).y == edge1[0].at(1).y) coord = 2;
	else if(edge1[0].at(0).z == edge1[0].at(1).z) coord = 3;

	/* calcolo le intersezioni */
	for(std::vector<double>::size_type d=0;d<edge1.size();d++){
		p0.x = edge1[d].at(0).x;
		p0.y = edge1[d].at(0).y;
		p0.z = edge1[d].at(0).z;
		p1.x = edge1[d].at(1).x;
		p1.y = edge1[d].at(1).y;
		p1.z = edge1[d].at(1).z;
		for(std::vector<double>::size_type c=0;c<edge2.size();c++){
			p2.x = edge2[c].at(0).x;
			p2.y = edge2[c].at(0).y;
			p2.z = edge2[c].at(0).z;
			p3.x = edge2[c].at(1).x;
			p3.y = edge2[c].at(1).y;
			p3.z = edge2[c].at(1).z;

			/**************************************************************
	            I due segmenti si intersecano se esiste (t,s) per cui:
	            p0.x + t*(p1.x - p0.x) = p2.x + s*(p3.x - p2.x)
	            p0.y + t*(p1.y - p0.y) = p2.y + s*(p3.y - p2.y)
	            p0.z + t*(p1.z - p0.z) = p2.z + s*(p3.z - p2.z)

	            Se esiste (t,s), basta sostituire in uno dei segmenti
	            il parametro ricavato per calcolare il punto di intersezione.

	            Quindi:
	            t*(p1.x - p0.x) + s*(p2.x - p3.x) = (p2.x - p0.x)
	            t*(p1.y - p0.y) + s*(p2.y - p3.y) = (p2.y - p0.y)
	            t*(p1.z - p0.z) + s*(p2.z - p3.z) = (p2.z - p0.z)

				Essendo le facce complanari,una delle 3 coordinate sarà uguale per tutti i punti.
				Se p0.z = p1.z = p2.z = p3.z :

				|(p2.x - p0.x) (p2.x - p3.x)|
	            |(p2.y - p0.y) (p2.y - p3.y)|
	            ----------------------------- = t
	            |(p1.x - p0.x) (p2.x - p3.x)|
	            |(p1.y - p0.y) (p2.y - p3.y)|

			 ***************************************************************/
			den = 0;
			switch (coord) {
			case 1:
				den = ((p1.y - p0.y)*(p2.z - p3.z))-((p2.y - p3.y)*(p1.z - p0.z));
				if(den!=0) num = ((p2.y - p0.y)*(p2.z - p3.z))-((p2.y - p3.y)*(p2.z - p0.z));
				break;
			case 2:
				den = ((p1.x - p0.x)*(p2.z - p3.z))-((p2.x - p3.x)*(p1.z - p0.z));
				if(den!=0) num = ((p2.x - p0.x)*(p2.z - p3.z))-((p2.x - p3.x)*(p2.z - p0.z));
				break;
			case 3:
				den = ((p1.x - p0.x)*(p2.y - p3.y))-((p2.x - p3.x)*(p1.y - p0.y));
				if(den!=0) num = ((p2.x - p0.x)*(p2.y - p3.y))-((p2.x - p3.x)*(p2.y - p0.y));
				break;
			default:
				printf("Errore in gen_setIntersect!!!\n");
				break;
			}

			/* Se si intersecano */
			if(den!=0){

				t = num/den;

				tmp.x = p0.x + t*(p1.x - p0.x);
				tmp.y = p0.y + t*(p1.y - p0.y);
				tmp.z = p0.z + t*(p1.z - p0.z);

				// se l'intersezione si trova sul segmento, salvo il punto
				if(gen_pointDsegment(tmp,p0,p1,0.000002) && gen_pointDsegment(tmp,p2,p3,0.000002)){
					pointQueue.push_back(tmp);
				}

			}
		}
	}

#if DEBUG_GLUE
	printf("----- DEBUG setIntersect -----\n");
	for(std::vector<double>::size_type g=0;g<pointQueue.size();g++){
		printf("p%d: %g %g %g\n",g+1,pointQueue[g].x,pointQueue[g].y,pointQueue[g].z);
	}
	printf("----- DEBUG setIntersect -----\n");
#endif

	return pointQueue;
}

/* Baricentro di una faccia */
Vertex gen_faceCenter(Mod_SubdivMesh *mesh,int f){

	int i;
	Vertex v;
	v.x = 0;
	v.y = 0;
	v.z = 0;

	for(i=0;i<mesh->face[f].nVert;i++){
		v.x=v.x+mesh->vert[mesh->face[f].vert[i]].x;
		v.y=v.y+mesh->vert[mesh->face[f].vert[i]].y;
		v.z=v.z+mesh->vert[mesh->face[f].vert[i]].z;
	}
	v.x = v.x/i;
	v.y = v.y/i;
	v.z = v.z/i;


	return v;
}

/* Funzione che, date due facce, determina quale delle due facce è interna all'altra */
int gen_faceInFace(Mod_SubdivMesh* mesh1,int f1,Mod_SubdivMesh* mesh2,int f2){

	int ret = 0;
	bool test = true;

	for(int i=0;i<mesh1->face[f1].nVert;i++){
		if(!gen_pnpoly(mesh2,f2,mesh1->vert[mesh1->face[f1].vert[i]])){
			test = false;
			break;
		}
	}
	if(test) ret = 1;

	if(ret==0){
		test = true;
		for(int i=0;i<mesh2->face[f2].nVert;i++){
			if(!gen_pnpoly(mesh1,f1,mesh2->vert[mesh2->face[f2].vert[i]])){
				test = false;
				break;
			}
		}
		if(test) ret = 2;
	}
	printf("La faccia interna è la %d\n",ret);
	return ret;
}

// Procedura che rimuove un punto da una lista di punti, non libera la memoria
bool removePoint(q_point *point,q_point **list, int *flag){

	q_point *tmp,*tmpp,*tmp2;
	bool ret = 0;
	//il flag deve essere modificato qui nella funzione
/*
	printf("rimuovo %g %g %g\n",point->v.x,point->v.y,point->v.z);
	tmp = *list;
    while(tmp!=NULL){
        printf("Lista da cui rimuovere: %g %g %g\n",tmp->v.x,tmp->v.y,tmp->v.z);
        tmp=tmp->next;
    }
*/

	if(*list==NULL) return false;

    tmpp = *list;
	tmp = tmpp->next;
	tmp2 = NULL;

	// se la lista ha un solo elemento, lo rimuovo se corrisponde al punto
	if(tmp==NULL && point->v.x==tmpp->v.x && point->v.y==tmpp->v.y && point->v.z==tmpp->v.z){
		ret = true;
		*list = NULL;
	}
	//cerco l'elemento nella lista e ne rimuovo tutte le istanze
	while(tmpp){
		// printf("tmpp %g %g %g  tmp %g %g %g\n",tmpp->v.x,tmpp->v.y,tmpp->v.z,tmp->v.x,tmp->v.y,tmp->v.z);
		if(tmp!=NULL && point->v.x==tmp->v.x && point->v.y==tmp->v.y && point->v.z==tmp->v.z){
			if(!ret) ret = true;
			// controllo il flag
			if(*flag==0){
				// conservo il puntatore
				tmp2 = tmp;
				*flag = 1;
			}
			// rimuovo dalla lista
			if(tmpp->next!=NULL){		// se non sono arrivato all'ultimo punto
				tmpp->next = tmp->next;
				tmp = tmpp->next;
				if(!tmp) tmp = *list;
			}
			else{						// il punto da rimuovere è il primo della lista
				*list = (*list)->next;
				tmpp = NULL;
			}
		}
		else{
			tmpp = tmpp->next;
			if(tmpp) tmp = tmpp->next;
			if(!tmp) tmp = *list;
		}

	}

	if(tmp2!=NULL){
		if(*list){
			tmp = *list;
			while(tmp->next!=NULL)
				tmp = tmp->next;
			tmp->next = tmp2;
			tmp2->next = NULL;
		}
		else
			tmp = tmp2;
	}

	/*
	//il primo elemento non va rimosso, ma va messo in coda per il controllo finale (solo se flag=0)
	if(tmpList != NULL && point->v.x == tmpList->v.x && point->v.y == tmpList->v.y && point->v.z == tmpList->v.z){
		if(*flag == 0){
			while(tmpList->next!=NULL)
				tmpList = tmpList->next;
			tmpList->next = *list;
			*list = (*list)->next;
			tmpList->next->next = NULL;
			*flag = 1;
		}
		else{
			*list = (*list)->next;
			//free(tmpList);
		}
	}
	else{
		while(tmpList!=NULL && (point->v.x != tmpList->v.x || point->v.y != tmpList->v.y || point->v.z != tmpList->v.z)){
			tmpPoint=tmpList;
			tmpList=tmpList->next;
		}
		if(tmpList!=NULL){
			tmpPoint->next=tmpList->next;
			// free(tmpList);
		}
	}
	 */
/*
	tmp = *list;
	while(tmp!=NULL){
		printf("Lista dopo la rimozione: %g %g %g\n",tmp->v.x,tmp->v.y,tmp->v.z);
		tmp=tmp->next;
	}
*/
	return ret;
}
// swap two int
void swap_int(int *a, int *b) {

	int temp;

	temp=*a;
	*a=*b;
	*b=temp;
}
// Print an error message
void ErrorMessage() {
	printf("ERROR: NO memory!!\n");
	exit(1);
}
